提交 4f987c2d 编写于 作者: M mindless

Add svn:eol-style and svn:keywords properties.


git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@13655 71c3de6d-444a-0410-be80-ed276b4c234a
上级 63eec22c
package hudson;
import java.io.File;
import java.io.IOException;
/**
* Pluggability point for how to create {@link PluginWrapper}.
*
* <p>
* This extension point was added to allow plugins to be loaded into a different environment
* (such as loading it in an existing DI container like Plexus.) A plugin strategy is a singleton
* instance, and as such this feature is primarily meant for OEM.
*
* See {@link PluginManager#createPluginStrategy()} for how this instance is created.
*/
public interface PluginStrategy extends ExtensionPoint {
/**
* Creates a plugin wrapper, which provides a management interface for the plugin
* @param archive
* @return
* @throws IOException
*/
public abstract PluginWrapper createPluginWrapper(File archive)
throws IOException;
/**
* Loads the plugin and starts it.
*
* <p>
* This should be done after all the classloaders are constructed for all
* the plugins, so that dependencies can be properly loaded by plugins.
*/
public abstract void load(PluginWrapper wrapper) throws IOException;
/**
* Optionally start services provided by the plugin. Should be called
* when all plugins are loaded.
*
* @param plugin
*/
public abstract void initializeComponents(PluginWrapper plugin);
package hudson;
import java.io.File;
import java.io.IOException;
/**
* Pluggability point for how to create {@link PluginWrapper}.
*
* <p>
* This extension point was added to allow plugins to be loaded into a different environment
* (such as loading it in an existing DI container like Plexus.) A plugin strategy is a singleton
* instance, and as such this feature is primarily meant for OEM.
*
* See {@link PluginManager#createPluginStrategy()} for how this instance is created.
*/
public interface PluginStrategy extends ExtensionPoint {
/**
* Creates a plugin wrapper, which provides a management interface for the plugin
* @param archive
* @return
* @throws IOException
*/
public abstract PluginWrapper createPluginWrapper(File archive)
throws IOException;
/**
* Loads the plugin and starts it.
*
* <p>
* This should be done after all the classloaders are constructed for all
* the plugins, so that dependencies can be properly loaded by plugins.
*/
public abstract void load(PluginWrapper wrapper) throws IOException;
/**
* Optionally start services provided by the plugin. Should be called
* when all plugins are loaded.
*
* @param plugin
*/
public abstract void initializeComponents(PluginWrapper plugin);
}
\ No newline at end of file
package hudson.model;
/**
* A listener for task related events from Executors
*
* @author Stephen Connolly
* @since 17-Jun-2008 18:58:12
*/
public interface ExecutorListener {
/**
* Called whenever a task is accepted by an executor.
* @param executor The executor.
* @param task The task.
*/
void taskAccepted(Executor executor, Queue.Task task);
/**
* Called whenever a task is completed without any problems by an executor.
* @param executor The executor.
* @param task The task.
* @param durationMS The number of milliseconds that the task took to complete.
*/
void taskCompleted(Executor executor, Queue.Task task, long durationMS);
/**
* Called whenever a task is completed without any problems by an executor.
* @param executor The executor.
* @param task The task.
* @param durationMS The number of milliseconds that the task took to complete.
* @param problems The exception that was thrown.
*/
void taskCompletedWithProblems(Executor executor, Queue.Task task, long durationMS, Throwable problems);
}
package hudson.model;
/**
* A listener for task related events from Executors
*
* @author Stephen Connolly
* @since 17-Jun-2008 18:58:12
*/
public interface ExecutorListener {
/**
* Called whenever a task is accepted by an executor.
* @param executor The executor.
* @param task The task.
*/
void taskAccepted(Executor executor, Queue.Task task);
/**
* Called whenever a task is completed without any problems by an executor.
* @param executor The executor.
* @param task The task.
* @param durationMS The number of milliseconds that the task took to complete.
*/
void taskCompleted(Executor executor, Queue.Task task, long durationMS);
/**
* Called whenever a task is completed without any problems by an executor.
* @param executor The executor.
* @param task The task.
* @param durationMS The number of milliseconds that the task took to complete.
* @param problems The exception that was thrown.
*/
void taskCompletedWithProblems(Executor executor, Queue.Task task, long durationMS, Throwable problems);
}
package hudson.model;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
public class JobParameterDefinition extends ParameterDefinition {
@DataBoundConstructor
public JobParameterDefinition(String name) {
super(name);
}
@Override
public ParameterDescriptor getDescriptor() {
return DESCRIPTOR;
}
public static final ParameterDescriptor DESCRIPTOR = new DescriptorImpl();
public static class DescriptorImpl extends ParameterDescriptor {
protected DescriptorImpl() {
super(JobParameterDefinition.class);
}
@Override
public String getDisplayName() {
return "Project Parameter";
}
@Override
public ParameterDefinition newInstance(StaplerRequest req, JSONObject formData) throws FormException {
return req.bindJSON(JobParameterDefinition.class, formData);
}
}
@Override
public ParameterValue createValue(StaplerRequest req, JSONObject jo) {
return req.bindJSON(JobParameterValue.class, jo);
}
}
package hudson.model;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
public class JobParameterDefinition extends ParameterDefinition {
@DataBoundConstructor
public JobParameterDefinition(String name) {
super(name);
}
@Override
public ParameterDescriptor getDescriptor() {
return DESCRIPTOR;
}
public static final ParameterDescriptor DESCRIPTOR = new DescriptorImpl();
public static class DescriptorImpl extends ParameterDescriptor {
protected DescriptorImpl() {
super(JobParameterDefinition.class);
}
@Override
public String getDisplayName() {
return "Project Parameter";
}
@Override
public ParameterDefinition newInstance(StaplerRequest req, JSONObject formData) throws FormException {
return req.bindJSON(JobParameterDefinition.class, formData);
}
}
@Override
public ParameterValue createValue(StaplerRequest req, JSONObject jo) {
return req.bindJSON(JobParameterValue.class, jo);
}
}
package hudson.model;
import org.kohsuke.stapler.DataBoundConstructor;
import java.util.Map;
public class JobParameterValue extends ParameterValue {
public final Job job;
@DataBoundConstructor
public JobParameterValue(String name, Job job) {
super(name);
this.job = job;
}
/**
* Exposes the name/value as an environment variable.
*/
@Override
public void buildEnvVars(AbstractBuild<?,?> build, Map<String,String> env) {
// TODO: check with Tom if this is really what he had in mind
env.put(name.toUpperCase(),job.toString());
}
}
package hudson.model;
import org.kohsuke.stapler.DataBoundConstructor;
import java.util.Map;
public class JobParameterValue extends ParameterValue {
public final Job job;
@DataBoundConstructor
public JobParameterValue(String name, Job job) {
super(name);
this.job = job;
}
/**
* Exposes the name/value as an environment variable.
*/
@Override
public void buildEnvVars(AbstractBuild<?,?> build, Map<String,String> env) {
// TODO: check with Tom if this is really what he had in mind
env.put(name.toUpperCase(),job.toString());
}
}
package hudson.model;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.servlet.ServletException;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
/**
* {@link View} that only contains projects for which the current user has access to.
*
* @since 1.220
* @author Tom Huybrechts
*/
public class MyView extends View {
private final Hudson owner;
private String description;
public MyView(Hudson owner) {
this.owner = owner;
}
@Override
public boolean contains(TopLevelItem item) {
return (item instanceof Job) && ((Job) item).hasPermission(Hudson.ADMINISTER);
}
@Override
public Item doCreateItem(StaplerRequest req, StaplerResponse rsp)
throws IOException, ServletException {
return owner.doCreateItem(req, rsp);
}
@Override
public String getDescription() {
return description;
}
/**
* Returns the transient {@link Action}s associated with the top page.
*
* @see Hudson#getActions()
*/
public List<Action> getActions() {
return Hudson.getInstance().getActions();
}
@Override
public TopLevelItem getItem(String name) {
return owner.getItem(name);
}
@Override
public Collection<TopLevelItem> getItems() {
List<TopLevelItem> items = new ArrayList<TopLevelItem>();
for (TopLevelItem item : owner.getItems()) {
if ((item instanceof Job) && ((Job) item).hasPermission(Job.CONFIGURE)) {
items.add(item);
}
}
return Collections.unmodifiableList(items);
}
@Override
public String getUrl() {
return "view/" + getViewName() + "/";
}
@Override
public String getViewName() {
return getDisplayName();
}
public String getDisplayName() {
return "My Projects";
}
public TopLevelItem getJob(String name) {
return getItem(name);
}
/**
* Accepts the new description.
*/
public synchronized void doSubmitDescription(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
checkPermission(CONFIGURE);
req.setCharacterEncoding("UTF-8");
description = req.getParameter("description");
owner.save();
rsp.sendRedirect("."); // go to the top page
}
}
package hudson.model;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.servlet.ServletException;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
/**
* {@link View} that only contains projects for which the current user has access to.
*
* @since 1.220
* @author Tom Huybrechts
*/
public class MyView extends View {
private final Hudson owner;
private String description;
public MyView(Hudson owner) {
this.owner = owner;
}
@Override
public boolean contains(TopLevelItem item) {
return (item instanceof Job) && ((Job) item).hasPermission(Hudson.ADMINISTER);
}
@Override
public Item doCreateItem(StaplerRequest req, StaplerResponse rsp)
throws IOException, ServletException {
return owner.doCreateItem(req, rsp);
}
@Override
public String getDescription() {
return description;
}
/**
* Returns the transient {@link Action}s associated with the top page.
*
* @see Hudson#getActions()
*/
public List<Action> getActions() {
return Hudson.getInstance().getActions();
}
@Override
public TopLevelItem getItem(String name) {
return owner.getItem(name);
}
@Override
public Collection<TopLevelItem> getItems() {
List<TopLevelItem> items = new ArrayList<TopLevelItem>();
for (TopLevelItem item : owner.getItems()) {
if ((item instanceof Job) && ((Job) item).hasPermission(Job.CONFIGURE)) {
items.add(item);
}
}
return Collections.unmodifiableList(items);
}
@Override
public String getUrl() {
return "view/" + getViewName() + "/";
}
@Override
public String getViewName() {
return getDisplayName();
}
public String getDisplayName() {
return "My Projects";
}
public TopLevelItem getJob(String name) {
return getItem(name);
}
/**
* Accepts the new description.
*/
public synchronized void doSubmitDescription(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
checkPermission(CONFIGURE);
req.setCharacterEncoding("UTF-8");
description = req.getParameter("description");
owner.save();
rsp.sendRedirect("."); // go to the top page
}
}
package hudson.model;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.StaplerRequest;
import hudson.util.DescriptorList;
import hudson.ExtensionPoint;
/**
* Defines a parameter for a build.
*
* <p>
* In Hudson, a user can configure a job to require parameters for a build.
* For example, imagine a test job that takes the bits to be tested as a parameter.
*
* <p>
* The actual meaning and the purpose of parameters are entirely up to users, so
* what the concrete parameter implmentation is pluggable. Write subclasses
* in a plugin and hook it up to {@link #LIST} to register it.
*
* <p>
* Three classes are used to model build parameters. First is the
* {@link ParameterDescriptor}, which tells Hudson what kind of implementations are
* available. From {@link ParameterDescriptor#newInstance(StaplerRequest, JSONObject)},
* Hudson creates {@link ParameterDefinition}s based on the job configuration.
* For example, if the user defines two string parameters "database-type" and
* "appserver-type", we'll get two {@link StringParameterDefinition} instances
* with their respective names.
*
* <p>
* When a job is configured with {@link ParameterDefinition} (or more precisely,
* {@link ParametersDefinitionProperty}, which in turns retains {@link ParameterDefinition}s),
* user would have to enter the values for the defined build parameters.
* The {@link #createValue(StaplerRequest, JSONObject)} method is used to convert this
* form submission into {@link ParameterValue} objects, which are then accessible
* during a build.
*
*
*
* <h2>Persistence</h2>
* <p>
* Instances of {@link ParameterDefinition}s are persisted into job <tt>config.xml</tt>
* through XStream.
*
*
* <h2>Assocaited Views</h2>
* <h4>config.jelly</h4>
* <p>
* {@link ParameterDefinition} class uses <tt>config.jelly</tt> to provide contribute a form
* fragment in the job configuration screen. Values entered there is fed back to
* {@link ParameterDescriptor#newInstance(StaplerRequest, JSONObject)} to create {@link ParameterDefinition}s.
*
* <h4>index.jelly</h4>
* The <tt>index.jelly</tt> view contributes a form fragment in the page where the user
* enters actual values of parameters for a build. The result of this form submission
* is then fed to {@link ParameterDefinition#createValue(StaplerRequest, JSONObject)} to
* create {@link ParameterValue}s.
*
* TODO: what Jelly pages does this object need for rendering UI?
* TODO: {@link ParameterValue} needs to have some mechanism to expose values to the build
* @see StringParameterDefinition
*/
public abstract class ParameterDefinition implements
Describable<ParameterDefinition>, ExtensionPoint {
private final String name;
public String getName() {
return name;
}
public ParameterDefinition(String name) {
super();
this.name = name;
}
/**
* {@inheritDoc}
*/
public abstract ParameterDescriptor getDescriptor();
public abstract ParameterValue createValue(StaplerRequest req, JSONObject jo);
/**
* Returns default parameter value for this definition.
*
* @return default parameter value or null if no defaults are available
* @since 1.253
*/
public ParameterValue getDefaultParameterValue() {
return null;
}
/**
* A list of available parameter definition types
*/
public static final DescriptorList<ParameterDefinition> LIST = new DescriptorList<ParameterDefinition>();
public abstract static class ParameterDescriptor extends
Descriptor<ParameterDefinition> {
protected ParameterDescriptor(Class<? extends ParameterDefinition> klazz) {
super(klazz);
}
public String getValuePage() {
return getViewPage(clazz, "index.jelly");
}
@Override
public String getDisplayName() {
return "Parameter";
}
}
}
package hudson.model;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.StaplerRequest;
import hudson.util.DescriptorList;
import hudson.ExtensionPoint;
/**
* Defines a parameter for a build.
*
* <p>
* In Hudson, a user can configure a job to require parameters for a build.
* For example, imagine a test job that takes the bits to be tested as a parameter.
*
* <p>
* The actual meaning and the purpose of parameters are entirely up to users, so
* what the concrete parameter implmentation is pluggable. Write subclasses
* in a plugin and hook it up to {@link #LIST} to register it.
*
* <p>
* Three classes are used to model build parameters. First is the
* {@link ParameterDescriptor}, which tells Hudson what kind of implementations are
* available. From {@link ParameterDescriptor#newInstance(StaplerRequest, JSONObject)},
* Hudson creates {@link ParameterDefinition}s based on the job configuration.
* For example, if the user defines two string parameters "database-type" and
* "appserver-type", we'll get two {@link StringParameterDefinition} instances
* with their respective names.
*
* <p>
* When a job is configured with {@link ParameterDefinition} (or more precisely,
* {@link ParametersDefinitionProperty}, which in turns retains {@link ParameterDefinition}s),
* user would have to enter the values for the defined build parameters.
* The {@link #createValue(StaplerRequest, JSONObject)} method is used to convert this
* form submission into {@link ParameterValue} objects, which are then accessible
* during a build.
*
*
*
* <h2>Persistence</h2>
* <p>
* Instances of {@link ParameterDefinition}s are persisted into job <tt>config.xml</tt>
* through XStream.
*
*
* <h2>Assocaited Views</h2>
* <h4>config.jelly</h4>
* <p>
* {@link ParameterDefinition} class uses <tt>config.jelly</tt> to provide contribute a form
* fragment in the job configuration screen. Values entered there is fed back to
* {@link ParameterDescriptor#newInstance(StaplerRequest, JSONObject)} to create {@link ParameterDefinition}s.
*
* <h4>index.jelly</h4>
* The <tt>index.jelly</tt> view contributes a form fragment in the page where the user
* enters actual values of parameters for a build. The result of this form submission
* is then fed to {@link ParameterDefinition#createValue(StaplerRequest, JSONObject)} to
* create {@link ParameterValue}s.
*
* TODO: what Jelly pages does this object need for rendering UI?
* TODO: {@link ParameterValue} needs to have some mechanism to expose values to the build
* @see StringParameterDefinition
*/
public abstract class ParameterDefinition implements
Describable<ParameterDefinition>, ExtensionPoint {
private final String name;
public String getName() {
return name;
}
public ParameterDefinition(String name) {
super();
this.name = name;
}
/**
* {@inheritDoc}
*/
public abstract ParameterDescriptor getDescriptor();
public abstract ParameterValue createValue(StaplerRequest req, JSONObject jo);
/**
* Returns default parameter value for this definition.
*
* @return default parameter value or null if no defaults are available
* @since 1.253
*/
public ParameterValue getDefaultParameterValue() {
return null;
}
/**
* A list of available parameter definition types
*/
public static final DescriptorList<ParameterDefinition> LIST = new DescriptorList<ParameterDefinition>();
public abstract static class ParameterDescriptor extends
Descriptor<ParameterDefinition> {
protected ParameterDescriptor(Class<? extends ParameterDefinition> klazz) {
super(klazz);
}
public String getValuePage() {
return getViewPage(clazz, "index.jelly");
}
@Override
public String getDisplayName() {
return "Parameter";
}
}
}
package hudson.model;
import hudson.tasks.BuildWrapper;
import hudson.tasks.Builder;
import hudson.util.VariableResolver;
import java.util.Map;
import org.kohsuke.stapler.StaplerRequest;
import net.sf.json.JSONObject;
/**
* A value for a parameter in a build.
*
* Created by {@link ParameterDefinition#createValue(StaplerRequest, JSONObject)} for
* a particular build (although this 'owner' build object is passed in for every method
* call as a parameter so that the parameter won't have to persist it.)
*
* <h2>Persistence</h2>
* <p>
* Instances of {@link ParameterValue}s are persisted into build's <tt>build.xml</tt>
* through XStream (via {@link ParametersAction}), so instances need to be persistable.
*
* <h2>Assocaited Views</h2>
* <h4>value.jelly</h4>
* The <tt>value.jelly</tt> view contributes a UI fragment to display the parameter
* values used for a build.
*
* <h2>Notes</h2>
* <ol>
* <li>{@link ParameterValue} is used to record values of the past build, but
* {@link ParameterDefinition} used back then might be gone already, or represent
* a different parameter now. So don't try to use the name to infer
* {@link ParameterDefinition} is.
* </ol>
* @see ParameterDefinition
*/
public abstract class ParameterValue {
protected final String name;
protected ParameterValue(String name) {
this.name = name;
}
/**
* Name of the parameter.
*
* This uniquely distinguishes {@link ParameterValue} among other parameters
* for the same build. This must be the same as {@link ParameterDefinition#getName()}.
*/
public final String getName() {
return name;
}
/**
* Adds environmental variables for the builds to the given map.
*
* <p>
* This provides a means for a parameter to pass the parameter
* values to the build to be performed.
*
* <p>
* When this method is invoked, the map already contains the
* current "planned export" list. The implementation is
* expected to add more values to this map (or do nothing)
*
* <p>
* Environment variables should be by convention all upper case.
* (This is so that a Windows/Unix heterogenous environment
* won't get inconsistent result depending on which platform to
* execute.)
*
* @param env
* never null.
* @param build
* The build for which this parameter is being used. Never null.
*/
public void buildEnvVars(AbstractBuild<?,?> build, Map<String,String> env) {
// no-op by default
}
/**
* Called at the beginning of a build to let a {@link ParameterValue}
* contributes a {@link BuildWrapper} to the build.
*
* <p>
* This provides a means for a parameter to perform more extensive
* set up / tear down during a build.
*
* @param build
* The build for which this parameter is being used. Never null.
* @return
* null if the parameter has no {@link BuildWrapper} to contribute to.
*/
public BuildWrapper createBuildWrapper(AbstractBuild<?,?> build) {
return null;
}
/**
* Returns a {@link VariableResolver} so that other components like {@link Builder}s
* can perform variable substitution to reflect parameter values into the build process.
*
* <p.
* This is yet another means in which a {@link ParameterValue} can influence
* a build.
*
* @param build
* The build for which this parameter is being used. Never null.
* @return
* if the parameter value is not interested in participating to the
* variable replacement process, return {@link VariableResolver#NONE}.
*/
public VariableResolver<String> createVariableResolver(AbstractBuild<?,?> build) {
return VariableResolver.NONE;
}
/**
* Accessing {@link ParameterDefinition} is not a good idea.
*
* @deprecated
* parameter definition may change any time. So if you find yourself
* in need of accessing the information from {@link ParameterDefinition},
* instead copy them in {@link ParameterDefinition#createValue(StaplerRequest, JSONObject)}
* into {@link ParameterValue}.
*/
public ParameterDefinition getDefinition() {
throw new UnsupportedOperationException();
}
}
package hudson.model;
import hudson.tasks.BuildWrapper;
import hudson.tasks.Builder;
import hudson.util.VariableResolver;
import java.util.Map;
import org.kohsuke.stapler.StaplerRequest;
import net.sf.json.JSONObject;
/**
* A value for a parameter in a build.
*
* Created by {@link ParameterDefinition#createValue(StaplerRequest, JSONObject)} for
* a particular build (although this 'owner' build object is passed in for every method
* call as a parameter so that the parameter won't have to persist it.)
*
* <h2>Persistence</h2>
* <p>
* Instances of {@link ParameterValue}s are persisted into build's <tt>build.xml</tt>
* through XStream (via {@link ParametersAction}), so instances need to be persistable.
*
* <h2>Assocaited Views</h2>
* <h4>value.jelly</h4>
* The <tt>value.jelly</tt> view contributes a UI fragment to display the parameter
* values used for a build.
*
* <h2>Notes</h2>
* <ol>
* <li>{@link ParameterValue} is used to record values of the past build, but
* {@link ParameterDefinition} used back then might be gone already, or represent
* a different parameter now. So don't try to use the name to infer
* {@link ParameterDefinition} is.
* </ol>
* @see ParameterDefinition
*/
public abstract class ParameterValue {
protected final String name;
protected ParameterValue(String name) {
this.name = name;
}
/**
* Name of the parameter.
*
* This uniquely distinguishes {@link ParameterValue} among other parameters
* for the same build. This must be the same as {@link ParameterDefinition#getName()}.
*/
public final String getName() {
return name;
}
/**
* Adds environmental variables for the builds to the given map.
*
* <p>
* This provides a means for a parameter to pass the parameter
* values to the build to be performed.
*
* <p>
* When this method is invoked, the map already contains the
* current "planned export" list. The implementation is
* expected to add more values to this map (or do nothing)
*
* <p>
* Environment variables should be by convention all upper case.
* (This is so that a Windows/Unix heterogenous environment
* won't get inconsistent result depending on which platform to
* execute.)
*
* @param env
* never null.
* @param build
* The build for which this parameter is being used. Never null.
*/
public void buildEnvVars(AbstractBuild<?,?> build, Map<String,String> env) {
// no-op by default
}
/**
* Called at the beginning of a build to let a {@link ParameterValue}
* contributes a {@link BuildWrapper} to the build.
*
* <p>
* This provides a means for a parameter to perform more extensive
* set up / tear down during a build.
*
* @param build
* The build for which this parameter is being used. Never null.
* @return
* null if the parameter has no {@link BuildWrapper} to contribute to.
*/
public BuildWrapper createBuildWrapper(AbstractBuild<?,?> build) {
return null;
}
/**
* Returns a {@link VariableResolver} so that other components like {@link Builder}s
* can perform variable substitution to reflect parameter values into the build process.
*
* <p.
* This is yet another means in which a {@link ParameterValue} can influence
* a build.
*
* @param build
* The build for which this parameter is being used. Never null.
* @return
* if the parameter value is not interested in participating to the
* variable replacement process, return {@link VariableResolver#NONE}.
*/
public VariableResolver<String> createVariableResolver(AbstractBuild<?,?> build) {
return VariableResolver.NONE;
}
/**
* Accessing {@link ParameterDefinition} is not a good idea.
*
* @deprecated
* parameter definition may change any time. So if you find yourself
* in need of accessing the information from {@link ParameterDefinition},
* instead copy them in {@link ParameterDefinition#createValue(StaplerRequest, JSONObject)}
* into {@link ParameterValue}.
*/
public ParameterDefinition getDefinition() {
throw new UnsupportedOperationException();
}
}
package hudson.model;
import hudson.model.Queue.Executable;
import hudson.util.QueueTaskFilter;
import java.io.IOException;
import java.util.List;
/**
* A task representing a project that should be built with a certain set of
* parameter values
*/
public class ParameterizedProjectTask extends QueueTaskFilter {
private final AbstractProject<?,?> project;
private final List<ParameterValue> parameters;
public ParameterizedProjectTask(AbstractProject<?,?> project, List<ParameterValue> parameters) {
super(project);
this.project = project;
this.parameters = parameters;
}
@Override
public Executable createExecutable() throws IOException {
AbstractBuild<?, ?> build = project.createExecutable();
build.addAction(new ParametersAction(parameters, build));
return build;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((parameters == null) ? 0 : parameters.hashCode());
result = prime * result + ((project == null) ? 0 : project.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ParameterizedProjectTask other = (ParameterizedProjectTask) obj;
if (parameters == null) {
if (other.parameters != null)
return false;
} else if (!parameters.equals(other.parameters)) {
return false;
}
if (project != other.project) {
return false;
}
return true;
}
}
package hudson.model;
import hudson.model.Queue.Executable;
import hudson.util.QueueTaskFilter;
import java.io.IOException;
import java.util.List;
/**
* A task representing a project that should be built with a certain set of
* parameter values
*/
public class ParameterizedProjectTask extends QueueTaskFilter {
private final AbstractProject<?,?> project;
private final List<ParameterValue> parameters;
public ParameterizedProjectTask(AbstractProject<?,?> project, List<ParameterValue> parameters) {
super(project);
this.project = project;
this.parameters = parameters;
}
@Override
public Executable createExecutable() throws IOException {
AbstractBuild<?, ?> build = project.createExecutable();
build.addAction(new ParametersAction(parameters, build));
return build;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((parameters == null) ? 0 : parameters.hashCode());
result = prime * result + ((project == null) ? 0 : project.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ParameterizedProjectTask other = (ParameterizedProjectTask) obj;
if (parameters == null) {
if (other.parameters != null)
return false;
} else if (!parameters.equals(other.parameters)) {
return false;
}
if (project != other.project) {
return false;
}
return true;
}
}
package hudson.model;
import hudson.Util;
import hudson.tasks.BuildWrapper;
import hudson.util.VariableResolver;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Records the parameter values used for a build.
*
* <P>
* This object is associated with the build record so that we remember what parameters
* were used for what build.
*/
public class ParametersAction implements Action, Iterable<ParameterValue> {
private final List<ParameterValue> parameters;
private final AbstractBuild<?, ?> build;
public ParametersAction(List<ParameterValue> parameters, AbstractBuild<?, ?> build) {
this.parameters = parameters;
this.build = build;
}
public void createBuildWrappers(AbstractBuild<?,?> build, Collection<? super BuildWrapper> result) {
for (ParameterValue p : parameters) {
BuildWrapper w = p.createBuildWrapper(build);
if(w!=null) result.add(w);
}
}
public void buildEnvVars(AbstractBuild<?,?> build, Map<String,String> env) {
for (ParameterValue p : parameters)
p.buildEnvVars(build,env);
}
/**
* Performs a variable subsitution to the given text and return it.
*/
public String substitute(AbstractBuild<?,?> build, String text) {
return Util.replaceMacro(text,createVariableResolver(build));
}
/**
* Creates an {@link VariableResolver} that aggregates all the parameters.
*/
public VariableResolver<String> createVariableResolver(AbstractBuild<?,?> build) {
VariableResolver[] resolvers = new VariableResolver[parameters.size()+1];
int i=0;
for (ParameterValue p : parameters)
resolvers[i++] = p.createVariableResolver(build);
resolvers[i] = build.getBuildVariableResolver();
return new VariableResolver.Union<String>(resolvers);
}
public AbstractBuild<?, ?> getBuild() {
return build;
}
public Iterator<ParameterValue> iterator() {
return parameters.iterator();
}
public List<ParameterValue> getParameters() {
return parameters;
}
@Override
public String getDisplayName() {
return Messages.ParameterAction_DisplayName();
}
@Override
public String getIconFileName() {
return "document-properties.gif";
}
@Override
public String getUrlName() {
return "parameters";
}
}
package hudson.model;
import hudson.Util;
import hudson.tasks.BuildWrapper;
import hudson.util.VariableResolver;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Records the parameter values used for a build.
*
* <P>
* This object is associated with the build record so that we remember what parameters
* were used for what build.
*/
public class ParametersAction implements Action, Iterable<ParameterValue> {
private final List<ParameterValue> parameters;
private final AbstractBuild<?, ?> build;
public ParametersAction(List<ParameterValue> parameters, AbstractBuild<?, ?> build) {
this.parameters = parameters;
this.build = build;
}
public void createBuildWrappers(AbstractBuild<?,?> build, Collection<? super BuildWrapper> result) {
for (ParameterValue p : parameters) {
BuildWrapper w = p.createBuildWrapper(build);
if(w!=null) result.add(w);
}
}
public void buildEnvVars(AbstractBuild<?,?> build, Map<String,String> env) {
for (ParameterValue p : parameters)
p.buildEnvVars(build,env);
}
/**
* Performs a variable subsitution to the given text and return it.
*/
public String substitute(AbstractBuild<?,?> build, String text) {
return Util.replaceMacro(text,createVariableResolver(build));
}
/**
* Creates an {@link VariableResolver} that aggregates all the parameters.
*/
public VariableResolver<String> createVariableResolver(AbstractBuild<?,?> build) {
VariableResolver[] resolvers = new VariableResolver[parameters.size()+1];
int i=0;
for (ParameterValue p : parameters)
resolvers[i++] = p.createVariableResolver(build);
resolvers[i] = build.getBuildVariableResolver();
return new VariableResolver.Union<String>(resolvers);
}
public AbstractBuild<?, ?> getBuild() {
return build;
}
public Iterator<ParameterValue> iterator() {
return parameters.iterator();
}
public List<ParameterValue> getParameters() {
return parameters;
}
@Override
public String getDisplayName() {
return Messages.ParameterAction_DisplayName();
}
@Override
public String getIconFileName() {
return "document-properties.gif";
}
@Override
public String getUrlName() {
return "parameters";
}
}
package hudson.model;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import javax.servlet.ServletException;
/**
* Keeps a list of the parameters defined for a project.
*
* <p>
* This class also implements {@link Action} so that <tt>index.jelly</tt> provides
* a form to enter build parameters.
*/
public class ParametersDefinitionProperty extends JobProperty<AbstractProject<?, ?>>
implements Action {
private final List<ParameterDefinition> parameterDefinitions;
public ParametersDefinitionProperty(List<ParameterDefinition> parameterDefinitions) {
this.parameterDefinitions = parameterDefinitions;
}
public AbstractProject<?,?> getOwner() {
return owner;
}
public List<ParameterDefinition> getParameterDefinitions() {
return parameterDefinitions;
}
@Override
public Action getJobAction(AbstractProject<?, ?> job) {
return this;
}
public AbstractProject<?, ?> getProject() {
return (AbstractProject<?, ?>) owner;
}
/**
* Interprets the form submission and schedules a build for a parameterized job.
*
* <p>
* This method is supposed to be invoked from {@link AbstractProject#doBuild(StaplerRequest, StaplerResponse)}.
*/
public void _doBuild(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
if(!req.getMethod().equals("POST")) {
// show the parameter entry form.
req.getView(this,"index.jelly").forward(req,rsp);
return;
}
List<ParameterValue> values = new ArrayList<ParameterValue>();
JSONObject formData = req.getSubmittedForm();
JSONArray a = JSONArray.fromObject(formData.get("parameter"));
for (Object o : a) {
JSONObject jo = (JSONObject) o;
String name = jo.getString("name");
ParameterDefinition d = getParameterDefinition(name);
if(d==null)
throw new IllegalArgumentException("No such parameter definition: " + name);
values.add(d.createValue(req, jo));
}
Hudson.getInstance().getQueue().add(
new ParameterizedProjectTask(owner, values), 0);
// send the user back to the job top page.
rsp.sendRedirect(".");
}
/**
* Gets the {@link ParameterDefinition} of the given name, if any.
*/
public ParameterDefinition getParameterDefinition(String name) {
for (ParameterDefinition pd : parameterDefinitions)
if (pd.getName().equals(name))
return pd;
return null;
}
@Override
public JobPropertyDescriptor getDescriptor() {
return DESCRIPTOR;
}
public static final JobPropertyDescriptor DESCRIPTOR = new DescriptorImpl();
public static class DescriptorImpl extends JobPropertyDescriptor {
protected DescriptorImpl() {
super(ParametersDefinitionProperty.class);
}
@Override
public boolean isApplicable(Class<? extends Job> jobType) {
return AbstractProject.class.isAssignableFrom(jobType);
}
@Override
public JobProperty<?> newInstance(StaplerRequest req,
JSONObject formData) throws FormException {
if (formData.isNullObject()) {
return null;
}
List<ParameterDefinition> parameterDefinitions = Descriptor.newInstancesFromHeteroList(
req, formData, "parameter", ParameterDefinition.LIST);
if(parameterDefinitions.isEmpty())
return null;
return new ParametersDefinitionProperty(parameterDefinitions);
}
@Override
public String getDisplayName() {
return Messages.ParametersDefinitionProperty_DisplayName();
}
}
@Override
public String getDisplayName() {
return null;
}
@Override
public String getIconFileName() {
return null;
}
@Override
public String getUrlName() {
return "parameters";
}
static {
ParameterDefinition.LIST.add(StringParameterDefinition.DESCRIPTOR);
ParameterDefinition.LIST.add(FileParameterDefinition.DESCRIPTOR);
}
}
package hudson.model;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import javax.servlet.ServletException;
/**
* Keeps a list of the parameters defined for a project.
*
* <p>
* This class also implements {@link Action} so that <tt>index.jelly</tt> provides
* a form to enter build parameters.
*/
public class ParametersDefinitionProperty extends JobProperty<AbstractProject<?, ?>>
implements Action {
private final List<ParameterDefinition> parameterDefinitions;
public ParametersDefinitionProperty(List<ParameterDefinition> parameterDefinitions) {
this.parameterDefinitions = parameterDefinitions;
}
public AbstractProject<?,?> getOwner() {
return owner;
}
public List<ParameterDefinition> getParameterDefinitions() {
return parameterDefinitions;
}
@Override
public Action getJobAction(AbstractProject<?, ?> job) {
return this;
}
public AbstractProject<?, ?> getProject() {
return (AbstractProject<?, ?>) owner;
}
/**
* Interprets the form submission and schedules a build for a parameterized job.
*
* <p>
* This method is supposed to be invoked from {@link AbstractProject#doBuild(StaplerRequest, StaplerResponse)}.
*/
public void _doBuild(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
if(!req.getMethod().equals("POST")) {
// show the parameter entry form.
req.getView(this,"index.jelly").forward(req,rsp);
return;
}
List<ParameterValue> values = new ArrayList<ParameterValue>();
JSONObject formData = req.getSubmittedForm();
JSONArray a = JSONArray.fromObject(formData.get("parameter"));
for (Object o : a) {
JSONObject jo = (JSONObject) o;
String name = jo.getString("name");
ParameterDefinition d = getParameterDefinition(name);
if(d==null)
throw new IllegalArgumentException("No such parameter definition: " + name);
values.add(d.createValue(req, jo));
}
Hudson.getInstance().getQueue().add(
new ParameterizedProjectTask(owner, values), 0);
// send the user back to the job top page.
rsp.sendRedirect(".");
}
/**
* Gets the {@link ParameterDefinition} of the given name, if any.
*/
public ParameterDefinition getParameterDefinition(String name) {
for (ParameterDefinition pd : parameterDefinitions)
if (pd.getName().equals(name))
return pd;
return null;
}
@Override
public JobPropertyDescriptor getDescriptor() {
return DESCRIPTOR;
}
public static final JobPropertyDescriptor DESCRIPTOR = new DescriptorImpl();
public static class DescriptorImpl extends JobPropertyDescriptor {
protected DescriptorImpl() {
super(ParametersDefinitionProperty.class);
}
@Override
public boolean isApplicable(Class<? extends Job> jobType) {
return AbstractProject.class.isAssignableFrom(jobType);
}
@Override
public JobProperty<?> newInstance(StaplerRequest req,
JSONObject formData) throws FormException {
if (formData.isNullObject()) {
return null;
}
List<ParameterDefinition> parameterDefinitions = Descriptor.newInstancesFromHeteroList(
req, formData, "parameter", ParameterDefinition.LIST);
if(parameterDefinitions.isEmpty())
return null;
return new ParametersDefinitionProperty(parameterDefinitions);
}
@Override
public String getDisplayName() {
return Messages.ParametersDefinitionProperty_DisplayName();
}
}
@Override
public String getDisplayName() {
return null;
}
@Override
public String getIconFileName() {
return null;
}
@Override
public String getUrlName() {
return "parameters";
}
static {
ParameterDefinition.LIST.add(StringParameterDefinition.DESCRIPTOR);
ParameterDefinition.LIST.add(FileParameterDefinition.DESCRIPTOR);
}
}
package hudson.model;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
public class RunParameterDefinition extends ParameterDefinition {
@DataBoundConstructor
public RunParameterDefinition(String name) {
super(name);
}
@Override
public ParameterDescriptor getDescriptor() {
return DESCRIPTOR;
}
public static final ParameterDescriptor DESCRIPTOR = new DescriptorImpl();
public static class DescriptorImpl extends ParameterDescriptor {
protected DescriptorImpl() {
super(RunParameterDefinition.class);
}
@Override
public String getDisplayName() {
return "Run Parameter";
}
@Override
public ParameterDefinition newInstance(StaplerRequest req, JSONObject formData) throws FormException {
return req.bindJSON(RunParameterDefinition.class, formData);
}
}
@Override
public ParameterValue createValue(StaplerRequest req, JSONObject jo) {
return req.bindJSON(RunParameterValue.class, jo);
}
}
package hudson.model;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
public class RunParameterDefinition extends ParameterDefinition {
@DataBoundConstructor
public RunParameterDefinition(String name) {
super(name);
}
@Override
public ParameterDescriptor getDescriptor() {
return DESCRIPTOR;
}
public static final ParameterDescriptor DESCRIPTOR = new DescriptorImpl();
public static class DescriptorImpl extends ParameterDescriptor {
protected DescriptorImpl() {
super(RunParameterDefinition.class);
}
@Override
public String getDisplayName() {
return "Run Parameter";
}
@Override
public ParameterDefinition newInstance(StaplerRequest req, JSONObject formData) throws FormException {
return req.bindJSON(RunParameterDefinition.class, formData);
}
}
@Override
public ParameterValue createValue(StaplerRequest req, JSONObject jo) {
return req.bindJSON(RunParameterValue.class, jo);
}
}
package hudson.model;
import org.kohsuke.stapler.DataBoundConstructor;
import java.util.Map;
public class RunParameterValue extends ParameterValue {
public final Run run;
@DataBoundConstructor
public RunParameterValue(String name, Run run) {
super(name);
this.run = run;
}
/**
* Exposes the name/value as an environment variable.
*/
@Override
public void buildEnvVars(AbstractBuild<?,?> build, Map<String,String> env) {
// TODO: check with Tom if this is really what he had in mind
env.put(name.toUpperCase(),run.toString());
}
}
package hudson.model;
import org.kohsuke.stapler.DataBoundConstructor;
import java.util.Map;
public class RunParameterValue extends ParameterValue {
public final Run run;
@DataBoundConstructor
public RunParameterValue(String name, Run run) {
super(name);
this.run = run;
}
/**
* Exposes the name/value as an environment variable.
*/
@Override
public void buildEnvVars(AbstractBuild<?,?> build, Map<String,String> env) {
// TODO: check with Tom if this is really what he had in mind
env.put(name.toUpperCase(),run.toString());
}
}
package hudson.model;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
/**
* Parameter whose value is a string value.
*/
public class StringParameterDefinition extends ParameterDefinition {
private String defaultValue;
@DataBoundConstructor
public StringParameterDefinition(String name, String defaultValue) {
super(name);
this.defaultValue = defaultValue;
}
@Override
public ParameterDescriptor getDescriptor() {
return DESCRIPTOR;
}
public String getDefaultValue() {
return defaultValue;
}
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
public StringParameterValue getDefaultParameterValue() {
return new StringParameterValue(getName(), defaultValue);
}
public static final ParameterDescriptor DESCRIPTOR = new DescriptorImpl();
public static class DescriptorImpl extends ParameterDescriptor {
protected DescriptorImpl() {
super(StringParameterDefinition.class);
}
@Override
public String getDisplayName() {
return Messages.StringParameterDefinition_DisplayName();
}
@Override
public String getHelpFile() {
return "/help/parameter/string.html";
}
}
@Override
public ParameterValue createValue(StaplerRequest req, JSONObject jo) {
return req.bindJSON(StringParameterValue.class, jo);
}
}
package hudson.model;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
/**
* Parameter whose value is a string value.
*/
public class StringParameterDefinition extends ParameterDefinition {
private String defaultValue;
@DataBoundConstructor
public StringParameterDefinition(String name, String defaultValue) {
super(name);
this.defaultValue = defaultValue;
}
@Override
public ParameterDescriptor getDescriptor() {
return DESCRIPTOR;
}
public String getDefaultValue() {
return defaultValue;
}
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
public StringParameterValue getDefaultParameterValue() {
return new StringParameterValue(getName(), defaultValue);
}
public static final ParameterDescriptor DESCRIPTOR = new DescriptorImpl();
public static class DescriptorImpl extends ParameterDescriptor {
protected DescriptorImpl() {
super(StringParameterDefinition.class);
}
@Override
public String getDisplayName() {
return Messages.StringParameterDefinition_DisplayName();
}
@Override
public String getHelpFile() {
return "/help/parameter/string.html";
}
}
@Override
public ParameterValue createValue(StaplerRequest req, JSONObject jo) {
return req.bindJSON(StringParameterValue.class, jo);
}
}
package hudson.model;
import org.kohsuke.stapler.DataBoundConstructor;
import java.util.Map;
import hudson.util.VariableResolver;
/**
* {@link ParameterValue} created from {@link StringParameterDefinition}.
*/
public class StringParameterValue extends ParameterValue {
public final String value;
@DataBoundConstructor
public StringParameterValue(String name, String value) {
super(name);
this.value = value;
}
/**
* Exposes the name/value as an environment variable.
*/
@Override
public void buildEnvVars(AbstractBuild<?,?> build, Map<String,String> env) {
env.put(name.toUpperCase(),value);
}
@Override
public VariableResolver<String> createVariableResolver(AbstractBuild<?, ?> build) {
return new VariableResolver<String>() {
public String resolve(String name) {
return StringParameterValue.this.name.equals(name) ? value : null;
}
};
}
@Override
public String toString() {
return "(StringParameterValue) " + getName() + "='" + value + "'";
}
}
package hudson.model;
import org.kohsuke.stapler.DataBoundConstructor;
import java.util.Map;
import hudson.util.VariableResolver;
/**
* {@link ParameterValue} created from {@link StringParameterDefinition}.
*/
public class StringParameterValue extends ParameterValue {
public final String value;
@DataBoundConstructor
public StringParameterValue(String name, String value) {
super(name);
this.value = value;
}
/**
* Exposes the name/value as an environment variable.
*/
@Override
public void buildEnvVars(AbstractBuild<?,?> build, Map<String,String> env) {
env.put(name.toUpperCase(),value);
}
@Override
public VariableResolver<String> createVariableResolver(AbstractBuild<?, ?> build) {
return new VariableResolver<String>() {
public String resolve(String name) {
return StringParameterValue.this.name.equals(name) ? value : null;
}
};
}
@Override
public String toString() {
return "(StringParameterValue) " + getName() + "='" + value + "'";
}
}
package hudson.security;
/**
* Object that has an {@link ACL}
*
* @since 1.220
* @see http://hudson.gotdns.com/wiki/display/HUDSON/Making+your+plugin+behave+in+secured+Hudson
*/
public interface AccessControlled {
/**
* Obtains the ACL associated with this object.
*
* @return never null.
*/
ACL getACL();
/**
* Convenient short-cut for {@code getACL().checkPermission(permission)}
*/
void checkPermission(Permission permission);
/**
* Convenient short-cut for {@code getACL().hasPermission(permission)}
*/
boolean hasPermission(Permission permission);
}
package hudson.security;
/**
* Object that has an {@link ACL}
*
* @since 1.220
* @see http://hudson.gotdns.com/wiki/display/HUDSON/Making+your+plugin+behave+in+secured+Hudson
*/
public interface AccessControlled {
/**
* Obtains the ACL associated with this object.
*
* @return never null.
*/
ACL getACL();
/**
* Convenient short-cut for {@code getACL().checkPermission(permission)}
*/
void checkPermission(Permission permission);
/**
* Convenient short-cut for {@code getACL().hasPermission(permission)}
*/
boolean hasPermission(Permission permission);
}
package hudson.security;
import hudson.model.Item;
import hudson.model.Job;
import hudson.model.JobProperty;
import hudson.model.JobPropertyDescriptor;
import hudson.model.Hudson;
import hudson.model.Run;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import net.sf.json.JSONObject;
import org.acegisecurity.Authentication;
import org.acegisecurity.acls.sid.GrantedAuthoritySid;
import org.acegisecurity.acls.sid.PrincipalSid;
import org.acegisecurity.acls.sid.Sid;
import org.kohsuke.stapler.StaplerRequest;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
/**
* {@link JobProperty} to associate ACL for each project.
*/
public class AuthorizationMatrixProperty extends JobProperty<Job<?, ?>> {
public static final JobPropertyDescriptor DESCRIPTOR = new DescriptorImpl();
private transient SidACL acl = new AclImpl();
private boolean useProjectSecurity;
public boolean isUseProjectSecurity() {
return useProjectSecurity;
}
public void setUseProjectSecurity(boolean useProjectSecurity) {
this.useProjectSecurity = useProjectSecurity;
}
/**
* List up all permissions that are granted.
*
* Strings are either the granted authority or the principal, which is not
* distinguished.
*/
private final Map<Permission, Set<String>> grantedPermissions = new HashMap<Permission, Set<String>>();
private Set<String> sids = new HashSet<String>();
public Set<String> getGroups() {
return sids;
}
/**
* Returns all SIDs configured in this matrix, minus "anonymous"
*
* @return Always non-null.
*/
public List<String> getAllSIDs() {
Set<String> r = new HashSet<String>();
for (Set<String> set : grantedPermissions.values())
r.addAll(set);
r.remove("anonymous");
String[] data = r.toArray(new String[r.size()]);
Arrays.sort(data);
return Arrays.asList(data);
}
/**
* Adds to {@link #grantedPermissions}. Use of this method should be limited
* during construction, as this object itself is considered immutable once
* populated.
*/
protected void add(Permission p, String sid) {
Set<String> set = grantedPermissions.get(p);
if (set == null)
grantedPermissions.put(p, set = new HashSet<String>());
set.add(sid);
sids.add(sid);
}
@Override
public JobPropertyDescriptor getDescriptor() {
return DESCRIPTOR;
}
public static class DescriptorImpl extends JobPropertyDescriptor {
@Override
public JobProperty<?> newInstance(StaplerRequest req,
JSONObject formData) throws FormException {
boolean useProjectSecurity = formData.has("useProjectSecurity");
AuthorizationMatrixProperty amp = new AuthorizationMatrixProperty();
amp.setUseProjectSecurity(useProjectSecurity);
for (Map.Entry<String, Object> r : (Set<Map.Entry<String, Object>>) formData
.getJSONObject("data").entrySet()) {
String sid = r.getKey();
if (r.getValue() instanceof JSONObject) {
for (Map.Entry<String, Boolean> e : (Set<Map.Entry<String, Boolean>>) ((JSONObject) r
.getValue()).entrySet()) {
if (e.getValue()) {
Permission p = Permission.fromId(e.getKey());
amp.add(p, sid);
}
}
}
}
return amp;
}
protected DescriptorImpl() {
super(AuthorizationMatrixProperty.class);
}
@Override
public boolean isApplicable(Class<? extends Job> jobType) {
// only applicable when ProjectMatrixAuthorizationStrategy is in charge
return Hudson.getInstance().getAuthorizationStrategy() instanceof ProjectMatrixAuthorizationStrategy;
}
@Override
public String getDisplayName() {
return "Authorization Matrix";
}
public List<PermissionGroup> getAllGroups() {
return Arrays.asList(PermissionGroup.get(Item.class),PermissionGroup.get(Run.class));
}
public boolean showPermission(Permission p) {
return p!=Item.CREATE;
}
}
private final class AclImpl extends SidACL {
protected Boolean hasPermission(Sid sid, Permission p) {
String s = toString(sid);
for (; p != null; p = p.impliedBy) {
Set<String> set = grantedPermissions.get(p);
if (set != null && set.contains(s))
return true;
}
return null;
}
protected Boolean _hasPermission(Authentication a, Permission permission) {
Boolean b = super._hasPermission(a, permission);
// permissions granted to anonymous users are granted to everyone
if (b == null)
b = hasPermission(ANONYMOUS, permission);
return b;
}
private String toString(Sid p) {
if (p instanceof GrantedAuthoritySid)
return ((GrantedAuthoritySid) p).getGrantedAuthority();
if (p instanceof PrincipalSid)
return ((PrincipalSid) p).getPrincipal();
// hmm...
return p.toString();
}
}
private Object readResolve() {
acl = new AclImpl();
return this;
}
public SidACL getACL() {
return acl;
}
/**
* Checks if the given SID has the given permission.
*/
public boolean hasPermission(String sid, Permission p) {
for (; p != null; p = p.impliedBy) {
Set<String> set = grantedPermissions.get(p);
if (set != null && set.contains(sid))
return true;
}
return false;
}
/**
* Works like {@link #add(Permission, String)} but takes both parameters
* from a single string of the form <tt>PERMISSIONID:sid</tt>
*/
private void add(String shortForm) {
int idx = shortForm.indexOf(':');
add(Permission.fromId(shortForm.substring(0, idx)), shortForm
.substring(idx + 1));
}
/**
* Persist {@link ProjectMatrixAuthorizationStrategy} as a list of IDs that
* represent {@link ProjectMatrixAuthorizationStrategy#grantedPermissions}.
*/
public static final class ConverterImpl implements Converter {
public boolean canConvert(Class type) {
return type == AuthorizationMatrixProperty.class;
}
public void marshal(Object source, HierarchicalStreamWriter writer,
MarshallingContext context) {
AuthorizationMatrixProperty amp = (AuthorizationMatrixProperty) source;
writer.startNode("useProjectSecurity");
context.convertAnother(Boolean.valueOf(amp.isUseProjectSecurity()));
writer.endNode();
for (Entry<Permission, Set<String>> e : amp.grantedPermissions
.entrySet()) {
String p = e.getKey().getId();
for (String sid : e.getValue()) {
writer.startNode("permission");
context.convertAnother(p + ':' + sid);
writer.endNode();
}
}
}
public Object unmarshal(HierarchicalStreamReader reader,
final UnmarshallingContext context) {
AuthorizationMatrixProperty as = new AuthorizationMatrixProperty();
String prop = reader.peekNextChild();
if (prop!=null && prop.equals("useProjectSecurity")) {
reader.moveDown();
Boolean useSecurity = (Boolean) context.convertAnother(as, Boolean.class);
as.setUseProjectSecurity(useSecurity.booleanValue());
reader.moveUp();
}
while (reader.hasMoreChildren()) {
reader.moveDown();
String id = (String) context.convertAnother(as, String.class);
as.add(id);
reader.moveUp();
}
return as;
}
}
}
package hudson.security;
import hudson.model.Item;
import hudson.model.Job;
import hudson.model.JobProperty;
import hudson.model.JobPropertyDescriptor;
import hudson.model.Hudson;
import hudson.model.Run;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import net.sf.json.JSONObject;
import org.acegisecurity.Authentication;
import org.acegisecurity.acls.sid.GrantedAuthoritySid;
import org.acegisecurity.acls.sid.PrincipalSid;
import org.acegisecurity.acls.sid.Sid;
import org.kohsuke.stapler.StaplerRequest;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
/**
* {@link JobProperty} to associate ACL for each project.
*/
public class AuthorizationMatrixProperty extends JobProperty<Job<?, ?>> {
public static final JobPropertyDescriptor DESCRIPTOR = new DescriptorImpl();
private transient SidACL acl = new AclImpl();
private boolean useProjectSecurity;
public boolean isUseProjectSecurity() {
return useProjectSecurity;
}
public void setUseProjectSecurity(boolean useProjectSecurity) {
this.useProjectSecurity = useProjectSecurity;
}
/**
* List up all permissions that are granted.
*
* Strings are either the granted authority or the principal, which is not
* distinguished.
*/
private final Map<Permission, Set<String>> grantedPermissions = new HashMap<Permission, Set<String>>();
private Set<String> sids = new HashSet<String>();
public Set<String> getGroups() {
return sids;
}
/**
* Returns all SIDs configured in this matrix, minus "anonymous"
*
* @return Always non-null.
*/
public List<String> getAllSIDs() {
Set<String> r = new HashSet<String>();
for (Set<String> set : grantedPermissions.values())
r.addAll(set);
r.remove("anonymous");
String[] data = r.toArray(new String[r.size()]);
Arrays.sort(data);
return Arrays.asList(data);
}
/**
* Adds to {@link #grantedPermissions}. Use of this method should be limited
* during construction, as this object itself is considered immutable once
* populated.
*/
protected void add(Permission p, String sid) {
Set<String> set = grantedPermissions.get(p);
if (set == null)
grantedPermissions.put(p, set = new HashSet<String>());
set.add(sid);
sids.add(sid);
}
@Override
public JobPropertyDescriptor getDescriptor() {
return DESCRIPTOR;
}
public static class DescriptorImpl extends JobPropertyDescriptor {
@Override
public JobProperty<?> newInstance(StaplerRequest req,
JSONObject formData) throws FormException {
boolean useProjectSecurity = formData.has("useProjectSecurity");
AuthorizationMatrixProperty amp = new AuthorizationMatrixProperty();
amp.setUseProjectSecurity(useProjectSecurity);
for (Map.Entry<String, Object> r : (Set<Map.Entry<String, Object>>) formData
.getJSONObject("data").entrySet()) {
String sid = r.getKey();
if (r.getValue() instanceof JSONObject) {
for (Map.Entry<String, Boolean> e : (Set<Map.Entry<String, Boolean>>) ((JSONObject) r
.getValue()).entrySet()) {
if (e.getValue()) {
Permission p = Permission.fromId(e.getKey());
amp.add(p, sid);
}
}
}
}
return amp;
}
protected DescriptorImpl() {
super(AuthorizationMatrixProperty.class);
}
@Override
public boolean isApplicable(Class<? extends Job> jobType) {
// only applicable when ProjectMatrixAuthorizationStrategy is in charge
return Hudson.getInstance().getAuthorizationStrategy() instanceof ProjectMatrixAuthorizationStrategy;
}
@Override
public String getDisplayName() {
return "Authorization Matrix";
}
public List<PermissionGroup> getAllGroups() {
return Arrays.asList(PermissionGroup.get(Item.class),PermissionGroup.get(Run.class));
}
public boolean showPermission(Permission p) {
return p!=Item.CREATE;
}
}
private final class AclImpl extends SidACL {
protected Boolean hasPermission(Sid sid, Permission p) {
String s = toString(sid);
for (; p != null; p = p.impliedBy) {
Set<String> set = grantedPermissions.get(p);
if (set != null && set.contains(s))
return true;
}
return null;
}
protected Boolean _hasPermission(Authentication a, Permission permission) {
Boolean b = super._hasPermission(a, permission);
// permissions granted to anonymous users are granted to everyone
if (b == null)
b = hasPermission(ANONYMOUS, permission);
return b;
}
private String toString(Sid p) {
if (p instanceof GrantedAuthoritySid)
return ((GrantedAuthoritySid) p).getGrantedAuthority();
if (p instanceof PrincipalSid)
return ((PrincipalSid) p).getPrincipal();
// hmm...
return p.toString();
}
}
private Object readResolve() {
acl = new AclImpl();
return this;
}
public SidACL getACL() {
return acl;
}
/**
* Checks if the given SID has the given permission.
*/
public boolean hasPermission(String sid, Permission p) {
for (; p != null; p = p.impliedBy) {
Set<String> set = grantedPermissions.get(p);
if (set != null && set.contains(sid))
return true;
}
return false;
}
/**
* Works like {@link #add(Permission, String)} but takes both parameters
* from a single string of the form <tt>PERMISSIONID:sid</tt>
*/
private void add(String shortForm) {
int idx = shortForm.indexOf(':');
add(Permission.fromId(shortForm.substring(0, idx)), shortForm
.substring(idx + 1));
}
/**
* Persist {@link ProjectMatrixAuthorizationStrategy} as a list of IDs that
* represent {@link ProjectMatrixAuthorizationStrategy#grantedPermissions}.
*/
public static final class ConverterImpl implements Converter {
public boolean canConvert(Class type) {
return type == AuthorizationMatrixProperty.class;
}
public void marshal(Object source, HierarchicalStreamWriter writer,
MarshallingContext context) {
AuthorizationMatrixProperty amp = (AuthorizationMatrixProperty) source;
writer.startNode("useProjectSecurity");
context.convertAnother(Boolean.valueOf(amp.isUseProjectSecurity()));
writer.endNode();
for (Entry<Permission, Set<String>> e : amp.grantedPermissions
.entrySet()) {
String p = e.getKey().getId();
for (String sid : e.getValue()) {
writer.startNode("permission");
context.convertAnother(p + ':' + sid);
writer.endNode();
}
}
}
public Object unmarshal(HierarchicalStreamReader reader,
final UnmarshallingContext context) {
AuthorizationMatrixProperty as = new AuthorizationMatrixProperty();
String prop = reader.peekNextChild();
if (prop!=null && prop.equals("useProjectSecurity")) {
reader.moveDown();
Boolean useSecurity = (Boolean) context.convertAnother(as, Boolean.class);
as.setUseProjectSecurity(useSecurity.booleanValue());
reader.moveUp();
}
while (reader.hasMoreChildren()) {
reader.moveDown();
String id = (String) context.convertAnother(as, String.class);
as.add(id);
reader.moveUp();
}
return as;
}
}
}
package hudson.security;
import hudson.model.AbstractProject;
import hudson.model.Descriptor;
import hudson.model.Jobs;
import hudson.util.RobustReflectionConverter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.mapper.Mapper;
import com.thoughtworks.xstream.core.JVM;
/**
* {@link GlobalMatrixAuthorizationStrategy} plus per-project ACL.
*
* <p>
* Per-project ACL is stored in {@link AuthorizationMatrixProperty}.
*
* @author Kohsuke Kawaguchi
*/
public class ProjectMatrixAuthorizationStrategy extends GlobalMatrixAuthorizationStrategy {
@Override
public ACL getACL(AbstractProject<?,?> project) {
AuthorizationMatrixProperty amp = project.getProperty(AuthorizationMatrixProperty.class);
if (amp != null && amp.isUseProjectSecurity()) {
return amp.getACL().newInheritingACL(getRootACL());
} else {
return getRootACL();
}
}
public Descriptor<AuthorizationStrategy> getDescriptor() {
return DESCRIPTOR;
}
public static final Descriptor<AuthorizationStrategy> DESCRIPTOR = new DescriptorImpl(ProjectMatrixAuthorizationStrategy.class) {
@Override
protected GlobalMatrixAuthorizationStrategy create() {
return new ProjectMatrixAuthorizationStrategy();
}
@Override
public String getDisplayName() {
return Messages.ProjectMatrixAuthorizationStrategy_DisplayName();
}
};
public static class ConverterImpl extends GlobalMatrixAuthorizationStrategy.ConverterImpl {
private RobustReflectionConverter ref;
public ConverterImpl(Mapper m) {
ref = new RobustReflectionConverter(m,new JVM().bestReflectionProvider());
}
protected GlobalMatrixAuthorizationStrategy create() {
return new ProjectMatrixAuthorizationStrategy();
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
String name = reader.peekNextChild();
if(name!=null && (name.equals("permission") || name.equals("useProjectSecurity")))
// the proper serialization form
return super.unmarshal(reader, context);
else
// remain compatible with earlier problem where we used reflection converter
return ref.unmarshal(reader,context);
}
public boolean canConvert(Class type) {
return type==ProjectMatrixAuthorizationStrategy.class;
}
}
static {
LIST.add(DESCRIPTOR);
Jobs.PROPERTIES.add(AuthorizationMatrixProperty.DESCRIPTOR);
}
}
package hudson.security;
import hudson.model.AbstractProject;
import hudson.model.Descriptor;
import hudson.model.Jobs;
import hudson.util.RobustReflectionConverter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.mapper.Mapper;
import com.thoughtworks.xstream.core.JVM;
/**
* {@link GlobalMatrixAuthorizationStrategy} plus per-project ACL.
*
* <p>
* Per-project ACL is stored in {@link AuthorizationMatrixProperty}.
*
* @author Kohsuke Kawaguchi
*/
public class ProjectMatrixAuthorizationStrategy extends GlobalMatrixAuthorizationStrategy {
@Override
public ACL getACL(AbstractProject<?,?> project) {
AuthorizationMatrixProperty amp = project.getProperty(AuthorizationMatrixProperty.class);
if (amp != null && amp.isUseProjectSecurity()) {
return amp.getACL().newInheritingACL(getRootACL());
} else {
return getRootACL();
}
}
public Descriptor<AuthorizationStrategy> getDescriptor() {
return DESCRIPTOR;
}
public static final Descriptor<AuthorizationStrategy> DESCRIPTOR = new DescriptorImpl(ProjectMatrixAuthorizationStrategy.class) {
@Override
protected GlobalMatrixAuthorizationStrategy create() {
return new ProjectMatrixAuthorizationStrategy();
}
@Override
public String getDisplayName() {
return Messages.ProjectMatrixAuthorizationStrategy_DisplayName();
}
};
public static class ConverterImpl extends GlobalMatrixAuthorizationStrategy.ConverterImpl {
private RobustReflectionConverter ref;
public ConverterImpl(Mapper m) {
ref = new RobustReflectionConverter(m,new JVM().bestReflectionProvider());
}
protected GlobalMatrixAuthorizationStrategy create() {
return new ProjectMatrixAuthorizationStrategy();
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
String name = reader.peekNextChild();
if(name!=null && (name.equals("permission") || name.equals("useProjectSecurity")))
// the proper serialization form
return super.unmarshal(reader, context);
else
// remain compatible with earlier problem where we used reflection converter
return ref.unmarshal(reader,context);
}
public boolean canConvert(Class type) {
return type==ProjectMatrixAuthorizationStrategy.class;
}
}
static {
LIST.add(DESCRIPTOR);
Jobs.PROPERTIES.add(AuthorizationMatrixProperty.DESCRIPTOR);
}
}
package hudson.slaves;
import hudson.ExtensionPoint;
import hudson.model.Computer;
import hudson.model.Describable;
import hudson.remoting.Channel.Listener;
import hudson.util.DescriptorList;
import hudson.util.StreamTaskListener;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Extension point to allow control over how {@link Computer}s are "launched",
* meaning how they get connected to their slave agent program.
*
* <p>
* <b>EXPERIMENTAL: SIGNATURE MAY CHANGE IN FUTURE RELEASES</b>
*
* @author Stephen Connolly
* @since 24-Apr-2008 22:12:35
*/
public abstract class ComputerLauncher implements Describable<ComputerLauncher>, ExtensionPoint {
/**
* Returns true if this {@link ComputerLauncher} supports
* programatic launch of the slave agent in the target {@link Computer}.
*/
public boolean isLaunchSupported() {
return true;
}
/**
* Launches the slave agent for the given {@link Computer}.
*
* <p>
* If the slave agent is launched successfully, {@link SlaveComputer#setChannel(InputStream, OutputStream, OutputStream, Listener)}
* should be invoked in the end to notify Hudson of the established connection.
* The operation could also fail, in which case there's no need to make any callback notification,
* (except to notify the user of the failure through {@link StreamTaskListener}.)
*
* @param listener
* The progress of the launch, as well as any error, should be sent to this listener.
*/
public abstract void launch(SlaveComputer computer, StreamTaskListener listener);
/**
* Allows the {@link ComputerLauncher} to tidy-up after a disconnect.
*/
public void afterDisconnect(SlaveComputer computer, StreamTaskListener listener) {
}
/**
* Allows the {@link ComputerLauncher} to prepare for a disconnect.
*/
public void beforeDisconnect(SlaveComputer computer, StreamTaskListener listener) {
}
/**
* All registered {@link ComputerLauncher} implementations.
*/
public static final DescriptorList<ComputerLauncher> LIST = new DescriptorList<ComputerLauncher>();
static {
LIST.load(JNLPLauncher.class);
LIST.load(CommandLauncher.class);
}
}
package hudson.slaves;
import hudson.ExtensionPoint;
import hudson.model.Computer;
import hudson.model.Describable;
import hudson.remoting.Channel.Listener;
import hudson.util.DescriptorList;
import hudson.util.StreamTaskListener;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Extension point to allow control over how {@link Computer}s are "launched",
* meaning how they get connected to their slave agent program.
*
* <p>
* <b>EXPERIMENTAL: SIGNATURE MAY CHANGE IN FUTURE RELEASES</b>
*
* @author Stephen Connolly
* @since 24-Apr-2008 22:12:35
*/
public abstract class ComputerLauncher implements Describable<ComputerLauncher>, ExtensionPoint {
/**
* Returns true if this {@link ComputerLauncher} supports
* programatic launch of the slave agent in the target {@link Computer}.
*/
public boolean isLaunchSupported() {
return true;
}
/**
* Launches the slave agent for the given {@link Computer}.
*
* <p>
* If the slave agent is launched successfully, {@link SlaveComputer#setChannel(InputStream, OutputStream, OutputStream, Listener)}
* should be invoked in the end to notify Hudson of the established connection.
* The operation could also fail, in which case there's no need to make any callback notification,
* (except to notify the user of the failure through {@link StreamTaskListener}.)
*
* @param listener
* The progress of the launch, as well as any error, should be sent to this listener.
*/
public abstract void launch(SlaveComputer computer, StreamTaskListener listener);
/**
* Allows the {@link ComputerLauncher} to tidy-up after a disconnect.
*/
public void afterDisconnect(SlaveComputer computer, StreamTaskListener listener) {
}
/**
* Allows the {@link ComputerLauncher} to prepare for a disconnect.
*/
public void beforeDisconnect(SlaveComputer computer, StreamTaskListener listener) {
}
/**
* All registered {@link ComputerLauncher} implementations.
*/
public static final DescriptorList<ComputerLauncher> LIST = new DescriptorList<ComputerLauncher>();
static {
LIST.load(JNLPLauncher.class);
LIST.load(CommandLauncher.class);
}
}
package hudson.slaves;
import hudson.ExtensionPoint;
import hudson.Util;
import hudson.model.Computer;
import hudson.model.Describable;
import hudson.model.Descriptor;
import hudson.util.DescriptorList;
import org.kohsuke.stapler.DataBoundConstructor;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Controls when to take {@link Computer} offline, bring it back online, or even to destroy it.
* <p/>
* <b>EXPERIMENTAL: SIGNATURE MAY CHANGE IN FUTURE RELEASES</b>
*
* @author Stephen Connolly
* @author Kohsuke Kawaguchi
*/
public abstract class RetentionStrategy<T extends Computer> implements Describable<RetentionStrategy<?>>, ExtensionPoint {
/**
* This method will be called periodically to allow this strategy to decide what to do with it's owning slave.
*
* @param c {@link Computer} for which this strategy is assigned. This object also exposes a bunch of properties
* that the callee can use to decide what action to take.
* @return The number of minutes after which the strategy would like to be checked again. The strategy may be
* rechecked earlier or later that this!
*/
public abstract long check(T c);
/**
* All registered {@link RetentionStrategy} implementations.
*/
public static final DescriptorList<RetentionStrategy<?>> LIST = new DescriptorList<RetentionStrategy<?>>();
/**
* Dummy instance that doesn't do any attempt to retention.
*/
public static final RetentionStrategy<Computer> NOOP = new RetentionStrategy<Computer>() {
public long check(Computer c) {
return 1;
}
public Descriptor<RetentionStrategy<?>> getDescriptor() {
throw new UnsupportedOperationException();
}
};
/**
* Convenient singleton instance, since this {@link RetentionStrategy} is stateless.
*/
public static final Always INSTANCE = new Always();
/**
* {@link RetentionStrategy} that tries to keep the node online all the time.
*/
public static class Always extends RetentionStrategy<SlaveComputer> {
/**
* Constructs a new Always.
*/
@DataBoundConstructor
public Always() {
}
/**
* {@inheritDoc}
*/
public long check(SlaveComputer c) {
if (c.isOffline() && c.isLaunchSupported())
c.tryReconnect();
return 1;
}
/**
* {@inheritDoc}
*/
public DescriptorImpl getDescriptor() {
return DESCRIPTOR;
}
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
private static class DescriptorImpl extends Descriptor<RetentionStrategy<?>> {
/**
* Constructs a new DescriptorImpl.
*/
public DescriptorImpl() {
super(Always.class);
}
/**
* {@inheritDoc}
*/
public String getDisplayName() {
return Messages.RetentionStrategy_Always_displayName();
}
}
static {
LIST.add(DESCRIPTOR);
}
}
/**
* {@link hudson.slaves.RetentionStrategy} that tries to keep the node offline when not in use.
*/
public static class Demand extends RetentionStrategy<SlaveComputer> {
private static final Logger logger = Logger.getLogger(Demand.class.getName());
/**
* The delay (in minutes) for which the slave must be in demand before tring to launch it.
*/
private final long inDemandDelay;
/**
* The delay (in minutes) for which the slave must be idle before taking it offline.
*/
private final long idleDelay;
@DataBoundConstructor
public Demand(long inDemandDelay, long idleDelay) {
this.inDemandDelay = Math.max(1, inDemandDelay);
this.idleDelay = Math.max(1, idleDelay);
}
/**
* Getter for property 'inDemandDelay'.
*
* @return Value for property 'inDemandDelay'.
*/
public long getInDemandDelay() {
return inDemandDelay;
}
/**
* Getter for property 'idleDelay'.
*
* @return Value for property 'idleDelay'.
*/
public long getIdleDelay() {
return idleDelay;
}
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
/**
* {@inheritDoc}
*/
public synchronized long check(SlaveComputer c) {
if (c.isOffline()) {
final long demandMilliseconds = System.currentTimeMillis() - c.getDemandStartMilliseconds();
if (demandMilliseconds > inDemandDelay * 1000 * 60 /*MINS->MILLIS*/) {
// we've been in demand for long enough
logger.log(Level.INFO, "Launching computer {0} as it has been in demand for {1}",
new Object[]{c.getNode().getNodeName(), Util.getTimeSpanString(demandMilliseconds)});
if (c.isLaunchSupported())
c.launch();
}
} else if (c.isIdle()) {
final long idleMilliseconds = System.currentTimeMillis() - c.getIdleStartMilliseconds();
if (idleMilliseconds > idleDelay * 1000 * 60 /*MINS->MILLIS*/) {
// we've been idle for long enough
logger.log(Level.INFO, "Disconnecting computer {0} as it has been idle for {1}",
new Object[]{c.getNode().getNodeName(), Util.getTimeSpanString(idleMilliseconds)});
c.disconnect();
}
}
return 1;
}
/**
* {@inheritDoc}
*/
public Descriptor<RetentionStrategy<?>> getDescriptor() {
return DESCRIPTOR;
}
private static class DescriptorImpl extends Descriptor<RetentionStrategy<?>> {
/**
* Constructs a new DescriptorImpl.
*/
public DescriptorImpl() {
super(Demand.class);
}
/**
* {@inheritDoc}
*/
public String getDisplayName() {
return Messages.RetentionStrategy_Demand_displayName();
}
}
static {
LIST.add(DESCRIPTOR);
}
}
static {
LIST.load(Demand.class);
}
}
package hudson.slaves;
import hudson.ExtensionPoint;
import hudson.Util;
import hudson.model.Computer;
import hudson.model.Describable;
import hudson.model.Descriptor;
import hudson.util.DescriptorList;
import org.kohsuke.stapler.DataBoundConstructor;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Controls when to take {@link Computer} offline, bring it back online, or even to destroy it.
* <p/>
* <b>EXPERIMENTAL: SIGNATURE MAY CHANGE IN FUTURE RELEASES</b>
*
* @author Stephen Connolly
* @author Kohsuke Kawaguchi
*/
public abstract class RetentionStrategy<T extends Computer> implements Describable<RetentionStrategy<?>>, ExtensionPoint {
/**
* This method will be called periodically to allow this strategy to decide what to do with it's owning slave.
*
* @param c {@link Computer} for which this strategy is assigned. This object also exposes a bunch of properties
* that the callee can use to decide what action to take.
* @return The number of minutes after which the strategy would like to be checked again. The strategy may be
* rechecked earlier or later that this!
*/
public abstract long check(T c);
/**
* All registered {@link RetentionStrategy} implementations.
*/
public static final DescriptorList<RetentionStrategy<?>> LIST = new DescriptorList<RetentionStrategy<?>>();
/**
* Dummy instance that doesn't do any attempt to retention.
*/
public static final RetentionStrategy<Computer> NOOP = new RetentionStrategy<Computer>() {
public long check(Computer c) {
return 1;
}
public Descriptor<RetentionStrategy<?>> getDescriptor() {
throw new UnsupportedOperationException();
}
};
/**
* Convenient singleton instance, since this {@link RetentionStrategy} is stateless.
*/
public static final Always INSTANCE = new Always();
/**
* {@link RetentionStrategy} that tries to keep the node online all the time.
*/
public static class Always extends RetentionStrategy<SlaveComputer> {
/**
* Constructs a new Always.
*/
@DataBoundConstructor
public Always() {
}
/**
* {@inheritDoc}
*/
public long check(SlaveComputer c) {
if (c.isOffline() && c.isLaunchSupported())
c.tryReconnect();
return 1;
}
/**
* {@inheritDoc}
*/
public DescriptorImpl getDescriptor() {
return DESCRIPTOR;
}
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
private static class DescriptorImpl extends Descriptor<RetentionStrategy<?>> {
/**
* Constructs a new DescriptorImpl.
*/
public DescriptorImpl() {
super(Always.class);
}
/**
* {@inheritDoc}
*/
public String getDisplayName() {
return Messages.RetentionStrategy_Always_displayName();
}
}
static {
LIST.add(DESCRIPTOR);
}
}
/**
* {@link hudson.slaves.RetentionStrategy} that tries to keep the node offline when not in use.
*/
public static class Demand extends RetentionStrategy<SlaveComputer> {
private static final Logger logger = Logger.getLogger(Demand.class.getName());
/**
* The delay (in minutes) for which the slave must be in demand before tring to launch it.
*/
private final long inDemandDelay;
/**
* The delay (in minutes) for which the slave must be idle before taking it offline.
*/
private final long idleDelay;
@DataBoundConstructor
public Demand(long inDemandDelay, long idleDelay) {
this.inDemandDelay = Math.max(1, inDemandDelay);
this.idleDelay = Math.max(1, idleDelay);
}
/**
* Getter for property 'inDemandDelay'.
*
* @return Value for property 'inDemandDelay'.
*/
public long getInDemandDelay() {
return inDemandDelay;
}
/**
* Getter for property 'idleDelay'.
*
* @return Value for property 'idleDelay'.
*/
public long getIdleDelay() {
return idleDelay;
}
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
/**
* {@inheritDoc}
*/
public synchronized long check(SlaveComputer c) {
if (c.isOffline()) {
final long demandMilliseconds = System.currentTimeMillis() - c.getDemandStartMilliseconds();
if (demandMilliseconds > inDemandDelay * 1000 * 60 /*MINS->MILLIS*/) {
// we've been in demand for long enough
logger.log(Level.INFO, "Launching computer {0} as it has been in demand for {1}",
new Object[]{c.getNode().getNodeName(), Util.getTimeSpanString(demandMilliseconds)});
if (c.isLaunchSupported())
c.launch();
}
} else if (c.isIdle()) {
final long idleMilliseconds = System.currentTimeMillis() - c.getIdleStartMilliseconds();
if (idleMilliseconds > idleDelay * 1000 * 60 /*MINS->MILLIS*/) {
// we've been idle for long enough
logger.log(Level.INFO, "Disconnecting computer {0} as it has been idle for {1}",
new Object[]{c.getNode().getNodeName(), Util.getTimeSpanString(idleMilliseconds)});
c.disconnect();
}
}
return 1;
}
/**
* {@inheritDoc}
*/
public Descriptor<RetentionStrategy<?>> getDescriptor() {
return DESCRIPTOR;
}
private static class DescriptorImpl extends Descriptor<RetentionStrategy<?>> {
/**
* Constructs a new DescriptorImpl.
*/
public DescriptorImpl() {
super(Demand.class);
}
/**
* {@inheritDoc}
*/
public String getDisplayName() {
return Messages.RetentionStrategy_Demand_displayName();
}
}
static {
LIST.add(DESCRIPTOR);
}
}
static {
LIST.load(Demand.class);
}
}
package hudson.tasks;
import hudson.ExtensionPoint;
import hudson.Plugin;
import hudson.scm.SCM;
import hudson.scm.CVSSCM;
import hudson.scm.SubversionSCM;
import hudson.model.User;
import hudson.model.AbstractProject;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Finds full name off the user when none is specified.
*
* <p>
* This is an extension point of Hudson. Plugins tha contribute new implementation
* of this class must register it to {@link #LIST}. The typical way to do this is:
*
* <pre>
* class PluginImpl extends {@link Plugin} {
* public void start() {
* ...
* UserNameResolver.LIST.add(new UserNameResolver());
* }
* }
* </pre>
*
* @author Kohsuke Kawaguchi
* @since 1.192
*/
public abstract class UserNameResolver implements ExtensionPoint {
/**
* Finds full name of the given user.
*
* <p>
* This method is called when a {@link User} without explicitly name is used.
*
* <p>
* When multiple resolvers are installed, they are consulted in order and
* the search will be over when a name is found by someoene.
*
* <p>
* Since {@link UserNameResolver} is singleton, this method can be invoked concurrently
* from multiple threads.
*
* @return
* null if the inference failed.
*/
public abstract String findNameFor(User u);
public static String resolve(User u) {
for (UserNameResolver r : LIST) {
String name = r.findNameFor(u);
if(name!=null) return name;
}
return null;
}
/**
* All registered {@link UserNameResolver} implementations.
*/
public static final List<UserNameResolver> LIST = new CopyOnWriteArrayList<UserNameResolver>();
}
package hudson.tasks;
import hudson.ExtensionPoint;
import hudson.Plugin;
import hudson.scm.SCM;
import hudson.scm.CVSSCM;
import hudson.scm.SubversionSCM;
import hudson.model.User;
import hudson.model.AbstractProject;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Finds full name off the user when none is specified.
*
* <p>
* This is an extension point of Hudson. Plugins tha contribute new implementation
* of this class must register it to {@link #LIST}. The typical way to do this is:
*
* <pre>
* class PluginImpl extends {@link Plugin} {
* public void start() {
* ...
* UserNameResolver.LIST.add(new UserNameResolver());
* }
* }
* </pre>
*
* @author Kohsuke Kawaguchi
* @since 1.192
*/
public abstract class UserNameResolver implements ExtensionPoint {
/**
* Finds full name of the given user.
*
* <p>
* This method is called when a {@link User} without explicitly name is used.
*
* <p>
* When multiple resolvers are installed, they are consulted in order and
* the search will be over when a name is found by someoene.
*
* <p>
* Since {@link UserNameResolver} is singleton, this method can be invoked concurrently
* from multiple threads.
*
* @return
* null if the inference failed.
*/
public abstract String findNameFor(User u);
public static String resolve(User u) {
for (UserNameResolver r : LIST) {
String name = r.findNameFor(u);
if(name!=null) return name;
}
return null;
}
/**
* All registered {@link UserNameResolver} implementations.
*/
public static final List<UserNameResolver> LIST = new CopyOnWriteArrayList<UserNameResolver>();
}
package hudson.util;
import hudson.ExtensionPoint;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
import java.util.Vector;
/**
* Servlet {@link Filter} that chains multiple {@link Filter}s, provided by plugins
*
* <p>
* While this class by itself is not an extension point, I'm marking this class
* as an extension point so that this class will be more discoverable.
*/
public class PluginServletFilter implements Filter, ExtensionPoint {
private static final List<Filter> LIST = new Vector<Filter>();
private static FilterConfig filterConfig;
public PluginServletFilter() {
}
public void init(FilterConfig filterConfig) throws ServletException {
PluginServletFilter.filterConfig = filterConfig;
synchronized (LIST) {
for (Filter f : LIST) {
f.init(filterConfig);
}
}
}
public static void addFilter(Filter filter) throws ServletException {
synchronized (LIST) {
if (filterConfig != null) {
filter.init(filterConfig);
}
LIST.add(filter);
}
}
public void doFilter(ServletRequest request, ServletResponse response, final FilterChain chain) throws IOException, ServletException {
new FilterChain() {
private int position=0;
// capture the array for thread-safety
private final Filter[] filters = LIST.toArray(new Filter[LIST.size()]);
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
if(position==filters.length) {
// reached to the end
chain.doFilter(request,response);
} else {
// call next
filters[position++].doFilter(request,response,this);
}
}
}.doFilter(request,response);
}
public void destroy() {
synchronized (LIST) {
for (Filter f : LIST)
f.destroy();
}
}
}
package hudson.util;
import hudson.ExtensionPoint;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
import java.util.Vector;
/**
* Servlet {@link Filter} that chains multiple {@link Filter}s, provided by plugins
*
* <p>
* While this class by itself is not an extension point, I'm marking this class
* as an extension point so that this class will be more discoverable.
*/
public class PluginServletFilter implements Filter, ExtensionPoint {
private static final List<Filter> LIST = new Vector<Filter>();
private static FilterConfig filterConfig;
public PluginServletFilter() {
}
public void init(FilterConfig filterConfig) throws ServletException {
PluginServletFilter.filterConfig = filterConfig;
synchronized (LIST) {
for (Filter f : LIST) {
f.init(filterConfig);
}
}
}
public static void addFilter(Filter filter) throws ServletException {
synchronized (LIST) {
if (filterConfig != null) {
filter.init(filterConfig);
}
LIST.add(filter);
}
}
public void doFilter(ServletRequest request, ServletResponse response, final FilterChain chain) throws IOException, ServletException {
new FilterChain() {
private int position=0;
// capture the array for thread-safety
private final Filter[] filters = LIST.toArray(new Filter[LIST.size()]);
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
if(position==filters.length) {
// reached to the end
chain.doFilter(request,response);
} else {
// call next
filters[position++].doFilter(request,response,this);
}
}
}.doFilter(request,response);
}
public void destroy() {
synchronized (LIST) {
for (Filter f : LIST)
f.destroy();
}
}
}
<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" xmlns:i="jelly:fmt">
<st:include page="/hudson/model/Job/_api.jelly" />
<h2>Disable/Enable a job</h2>
<p>
To programmatically disable a job, post to <a href="../disable">this URL</a>.
Similarly post to <a href="../enable">this URL</a> for enabling this job.
</p>
<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" xmlns:i="jelly:fmt">
<st:include page="/hudson/model/Job/_api.jelly" />
<h2>Disable/Enable a job</h2>
<p>
To programmatically disable a job, post to <a href="../disable">this URL</a>.
Similarly post to <a href="../enable">this URL</a> for enabling this job.
</p>
</j:jelly>
\ No newline at end of file
<!-- display permalinks of the page -->
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler">
<!-- give properties a chance to contribute summary item -->
<j:forEach var="p" items="${it.properties.values()}">
<st:include page="summary.jelly" from="${p}" optional="true" it="${p}" />
<!-- give properties a chance to contribute summary item -->
<j:forEach var="p" items="${it.properties.values()}">
<st:include page="summary.jelly" from="${p}" optional="true" it="${p}" />
</j:forEach>
</j:jelly>
\ No newline at end of file
</j:jelly>
<div>
This view has no jobs.
<div>
This view has no jobs.
</div>
\ No newline at end of file
<!--
This Jelly view shows UI for configuring parameter definitions as a part of the job configuration.
-->
<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"
xmlns:i="jelly:fmt" xmlns:p="/lib/hudson/project">
<f:textbox name="parameter.name" value="${instance.name}"/>
<!--
This Jelly view shows UI for configuring parameter definitions as a part of the job configuration.
-->
<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"
xmlns:i="jelly:fmt" xmlns:p="/lib/hudson/project">
<f:textbox name="parameter.name" value="${instance.name}"/>
</j:jelly>
\ No newline at end of file
<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"
xmlns:i="jelly:fmt" xmlns:p="/lib/hudson/project">
<l:layout title="${it.displayName}">
<st:include page="sidepanel.jelly" it="${it.build}" />
<l:main-panel>
<h1>${%Build} #${it.build.number}</h1>
<l:pane title="${%Parameters}" width="3">
<j:forEach var="parameterValue" items="${it.parameters}">
<st:include it="${parameterValue}"
page="value.jelly" />
</j:forEach>
</l:pane>
</l:main-panel>
</l:layout>
</j:jelly>
<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"
xmlns:i="jelly:fmt" xmlns:p="/lib/hudson/project">
<l:layout title="${it.displayName}">
<st:include page="sidepanel.jelly" it="${it.build}" />
<l:main-panel>
<h1>${%Build} #${it.build.number}</h1>
<l:pane title="${%Parameters}" width="3">
<j:forEach var="parameterValue" items="${it.parameters}">
<st:include it="${parameterValue}"
page="value.jelly" />
</j:forEach>
</l:pane>
</l:main-panel>
</l:layout>
</j:jelly>
<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">
<f:optionalBlock name="useProjectSecurity" title="${%Enable project-based security}" checked="${instance.isUseProjectSecurity()}">
<st:include page="/hudson/security/GlobalMatrixAuthorizationStrategy/config.jelly" />
</f:optionalBlock>
<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">
<f:optionalBlock name="useProjectSecurity" title="${%Enable project-based security}" checked="${instance.isUseProjectSecurity()}">
<st:include page="/hudson/security/GlobalMatrixAuthorizationStrategy/config.jelly" />
</f:optionalBlock>
</j:jelly>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册