org.jenkins-ci
diff --git a/core/src/main/java/hudson/FilePath.java b/core/src/main/java/hudson/FilePath.java
index 4bbb0171fdb3a909cb0e0a1b7dd9a3aa5b543a09..e42035bd4f45dce00abd31e623ae64287c6c875b 100644
--- a/core/src/main/java/hudson/FilePath.java
+++ b/core/src/main/java/hudson/FilePath.java
@@ -111,6 +111,7 @@ import java.util.regex.Pattern;
import static hudson.FilePath.TarCompression.*;
import static hudson.Util.*;
+import javax.annotation.Nonnull;
/**
* {@link File} like object with remoting support.
@@ -1161,7 +1162,7 @@ public final class FilePath implements Serializable {
* @param relOrAbsolute a relative or absolute path
* @return a file on the same channel
*/
- public FilePath child(String relOrAbsolute) {
+ public @Nonnull FilePath child(String relOrAbsolute) {
return new FilePath(this,relOrAbsolute);
}
diff --git a/core/src/main/java/hudson/Launcher.java b/core/src/main/java/hudson/Launcher.java
index e427eee4a0c545f809d42197d7ccf8fad9833ad8..0d50a39166d6b82edc951d53871450c41516e988 100644
--- a/core/src/main/java/hudson/Launcher.java
+++ b/core/src/main/java/hudson/Launcher.java
@@ -1009,7 +1009,7 @@ public abstract class Launcher {
*
* @author rcampbell
* @author Oleg Nenashev, Synopsys Inc.
- * @since TODO: define version
+ * @since 1.568
*/
public static class DecoratedLauncher extends Launcher {
diff --git a/core/src/main/java/hudson/diagnosis/ReverseProxySetupMonitor.java b/core/src/main/java/hudson/diagnosis/ReverseProxySetupMonitor.java
index 79e1685f6014b139451f17e75ed168bbbcfde750..94412637bfcd20a22c138bafd6853c8086b11606 100644
--- a/core/src/main/java/hudson/diagnosis/ReverseProxySetupMonitor.java
+++ b/core/src/main/java/hudson/diagnosis/ReverseProxySetupMonitor.java
@@ -74,7 +74,7 @@ public class ReverseProxySetupMonitor extends AdministrativeMonitor {
assert j != null;
String inferred = j.getRootUrlFromRequest() + "manage";
// TODO this could also verify that j.getRootUrl() has been properly configured, and send a different message if not
- if (rest.equals(inferred)) {
+ if (rest.startsWith(inferred)) { // not using equals due to JENKINS-24014
throw HttpResponses.ok();
} else {
LOGGER.log(Level.WARNING, "{0} vs. {1}", new Object[] {inferred, rest});
diff --git a/core/src/main/java/hudson/model/AbstractBuild.java b/core/src/main/java/hudson/model/AbstractBuild.java
index d1e291d52eeb494298c9bca2dddca19c7425aa96..28ef3ff5e83c985d5da9b9b8a2018d298589871d 100644
--- a/core/src/main/java/hudson/model/AbstractBuild.java
+++ b/core/src/main/java/hudson/model/AbstractBuild.java
@@ -292,7 +292,7 @@ public abstract class AbstractBuild,R extends Abs
* Normally, a workspace is assigned by {@link hudson.model.Run.RunExecution}, but this lets you set the workspace in case
* {@link AbstractBuild} is created without a build.
*/
- protected void setWorkspace(FilePath ws) {
+ protected void setWorkspace(@Nonnull FilePath ws) {
this.workspace = ws.getRemote();
}
diff --git a/core/src/main/java/hudson/model/AbstractProject.java b/core/src/main/java/hudson/model/AbstractProject.java
index 6e36007578c0de655d69a83dd17fe11cd9555bf8..947c5179f782d9aed64470267b9ef202d8494047 100644
--- a/core/src/main/java/hudson/model/AbstractProject.java
+++ b/core/src/main/java/hudson/model/AbstractProject.java
@@ -1432,7 +1432,7 @@ public abstract class AbstractProject
,R extends A
}
}
- private PollingResult pollWithWorkspace(TaskListener listener, SCM scm, R lb, FilePath ws, WorkspaceList l) throws InterruptedException, IOException {
+ private PollingResult pollWithWorkspace(TaskListener listener, SCM scm, R lb, @Nonnull FilePath ws, WorkspaceList l) throws InterruptedException, IOException {
// if doing non-concurrent build, acquire a workspace in a way that causes builds to block for this workspace.
// this prevents multiple workspaces of the same job --- the behavior of Hudson < 1.319.
//
diff --git a/core/src/main/java/hudson/model/ExecutorListener.java b/core/src/main/java/hudson/model/ExecutorListener.java
index 0588c834aae81e1772b437e70bd8a535acd8d0b1..3c5e221f17f277d8bc2a9c53a3e587e36039f9cd 100644
--- a/core/src/main/java/hudson/model/ExecutorListener.java
+++ b/core/src/main/java/hudson/model/ExecutorListener.java
@@ -23,11 +23,13 @@
*/
package hudson.model;
+import hudson.slaves.SlaveComputer;
+
/**
- * A listener for task related events from Executors
-*
+ * A listener for task related events from executors.
+ * A {@link Computer#getRetentionStrategy} or {@link SlaveComputer#getLauncher} may implement this interface.
* @author Stephen Connolly
-* @since 17-Jun-2008 18:58:12
+* @since 1.312
*/
public interface ExecutorListener {
@@ -47,7 +49,7 @@ public interface ExecutorListener {
void taskCompleted(Executor executor, Queue.Task task, long durationMS);
/**
- * Called whenever a task is completed without any problems by an executor.
+ * Called whenever a task is completed with some problems by an executor.
* @param executor The executor.
* @param task The task.
* @param durationMS The number of milliseconds that the task took to complete.
diff --git a/core/src/main/java/hudson/model/HealthReport.java b/core/src/main/java/hudson/model/HealthReport.java
index 2e1efe05f8679795842af44c1357fbd6aa2460f1..bf8c776d77b3a98c900533e1ad242dc698b93afe 100644
--- a/core/src/main/java/hudson/model/HealthReport.java
+++ b/core/src/main/java/hudson/model/HealthReport.java
@@ -34,7 +34,9 @@ import org.kohsuke.stapler.export.ExportedBean;
import java.io.*;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* Represents health of something (typically project).
@@ -60,6 +62,15 @@ public class HealthReport implements Serializable, Comparable {
private static final String HEALTH_0_TO_20_IMG = "health-00to19.png";
private static final String HEALTH_UNKNOWN_IMG = "empty.png";
+ private static final Map iconIMGToClassMap = new HashMap();
+ static {
+ iconIMGToClassMap.put(HEALTH_OVER_80_IMG, HEALTH_OVER_80);
+ iconIMGToClassMap.put(HEALTH_61_TO_80_IMG, HEALTH_61_TO_80);
+ iconIMGToClassMap.put(HEALTH_41_TO_60_IMG, HEALTH_41_TO_60);
+ iconIMGToClassMap.put(HEALTH_21_TO_40_IMG, HEALTH_21_TO_40);
+ iconIMGToClassMap.put(HEALTH_0_TO_20_IMG, HEALTH_0_TO_20);
+ }
+
/**
* The percentage health score (from 0 to 100 inclusive).
*/
@@ -351,6 +362,10 @@ public class HealthReport implements Serializable, Comparable {
hr.localizibleDescription = new NonLocalizable(hr.description == null ? "" : hr.description);
OldDataMonitor.report(context, "1.256");
}
+
+ if (hr.iconClassName == null && hr.iconUrl != null && iconIMGToClassMap.containsKey(hr.iconUrl)) {
+ hr.iconClassName = iconIMGToClassMap.get(hr.iconUrl);
+ }
}
}
}
diff --git a/core/src/main/java/hudson/model/Item.java b/core/src/main/java/hudson/model/Item.java
index d0931b85f7019fb7ada2f215f4e64b8023f24f88..726796fa8e673bb118386237d4bbcefcaeb15570 100644
--- a/core/src/main/java/hudson/model/Item.java
+++ b/core/src/main/java/hudson/model/Item.java
@@ -224,7 +224,7 @@ public interface Item extends PersistenceRoot, SearchableModelObject, AccessCont
Permission DELETE = new Permission(PERMISSIONS, "Delete", Messages._Item_DELETE_description(), Permission.DELETE, PermissionScope.ITEM);
Permission CONFIGURE = new Permission(PERMISSIONS, "Configure", Messages._Item_CONFIGURE_description(), Permission.CONFIGURE, PermissionScope.ITEM);
Permission READ = new Permission(PERMISSIONS, "Read", Messages._Item_READ_description(), Permission.READ, PermissionScope.ITEM);
- Permission DISCOVER = new Permission(PERMISSIONS, "Discover", Messages._AbstractProject_DiscoverPermission_Description(), Permission.READ, PermissionScope.ITEM);
+ Permission DISCOVER = new Permission(PERMISSIONS, "Discover", Messages._AbstractProject_DiscoverPermission_Description(), READ, PermissionScope.ITEM);
Permission EXTENDED_READ = new Permission(PERMISSIONS,"ExtendedRead", Messages._AbstractProject_ExtendedReadPermission_Description(), CONFIGURE, Boolean.getBoolean("hudson.security.ExtendedReadPermission"), new PermissionScope[]{PermissionScope.ITEM});
// TODO the following really belong in Job, not Item, but too late to move since the owner.name is encoded in the ID:
Permission BUILD = new Permission(PERMISSIONS, "Build", Messages._AbstractProject_BuildPermission_Description(), Permission.UPDATE, PermissionScope.ITEM);
diff --git a/core/src/main/java/hudson/model/ItemGroup.java b/core/src/main/java/hudson/model/ItemGroup.java
index bc042c8925fe27963d1e07691a4365f8d431364c..ace90e16b4354ec2f98dd022e7dce4d9cced37f6 100644
--- a/core/src/main/java/hudson/model/ItemGroup.java
+++ b/core/src/main/java/hudson/model/ItemGroup.java
@@ -28,6 +28,7 @@ import java.io.IOException;
import java.util.Collection;
import java.io.File;
import javax.annotation.CheckForNull;
+import org.acegisecurity.AccessDeniedException;
/**
* Represents a grouping inherent to a kind of {@link Item}s.
@@ -67,8 +68,10 @@ public interface ItemGroup extends PersistenceRoot, ModelObject
/**
* Gets the {@link Item} inside this group that has a given name, or null if it does not exist.
+ * @throws AccessDeniedException if the current user has {@link Item#DISCOVER} but not {@link Item#READ} on this item
+ * @return an item whose {@link Item#getName} is {@code name} and whose {@link Item#getParent} is {@code this}, or null if there is no such item, or there is but the current user lacks both {@link Item#DISCOVER} and {@link Item#READ} on it
*/
- @CheckForNull T getItem(String name);
+ @CheckForNull T getItem(String name) throws AccessDeniedException;
/**
* Assigns the {@link Item#getRootDir() root directory} for children.
diff --git a/core/src/main/java/hudson/model/Job.java b/core/src/main/java/hudson/model/Job.java
index 9f5bb63c72f8cb3ea03d0d20b4ef755fd17737de..e7aebb77d297371ac9e0c26cb7898d20fcdb231a 100644
--- a/core/src/main/java/hudson/model/Job.java
+++ b/core/src/main/java/hudson/model/Job.java
@@ -619,6 +619,9 @@ public abstract class Job, RunT extends Run, Mod
return getUrl();
}
+ /**
+ * Returns true iff this label is an atom.
+ *
+ * @since 1.580
+ */
+ public boolean isAtom() { return false; }
+
/**
* Evaluates whether the label expression is true given the specified value assignment.
* IOW, returns true if the assignment provided by the resolver matches this label expression.
diff --git a/core/src/main/java/hudson/model/Queue.java b/core/src/main/java/hudson/model/Queue.java
index 4b314ad78a9df99910e93d0f7cc7ebddab9a2ab9..830eb851f66eb14fc79d503ea4dae4e4bbd45649 100644
--- a/core/src/main/java/hudson/model/Queue.java
+++ b/core/src/main/java/hudson/model/Queue.java
@@ -1073,16 +1073,20 @@ public class Queue extends ResourceController implements Saveable {
private void makeBuildable(BuildableItem p) {
if(Jenkins.FLYWEIGHT_SUPPORT && p.task instanceof FlyweightTask && !ifBlockedByHudsonShutdown(p.task)) {
- ConsistentHash hash = new ConsistentHash(new Hash() {
- public String hash(Node node) {
- return node.getNodeName();
- }
- });
+
+
Jenkins h = Jenkins.getInstance();
+ Map hashSource = new HashMap(h.getNodes().size());
+
// Even if master is configured with zero executors, we may need to run a flyweight task like MatrixProject on it.
- hash.add(h, Math.max(h.getNumExecutors()*100, 1));
- for (Node n : h.getNodes())
- hash.add(n, n.getNumExecutors()*100);
+ hashSource.put(h, Math.max(h.getNumExecutors() * 100, 1));
+
+ for (Node n : h.getNodes()) {
+ hashSource.put(n, n.getNumExecutors() * 100);
+ }
+
+ ConsistentHash hash = new ConsistentHash(NODE_HASH);
+ hash.addAll(hashSource);
Label lbl = p.getAssignedLabel();
for (Node n : hash.list(p.task.getFullDisplayName())) {
@@ -1101,6 +1105,13 @@ public class Queue extends ResourceController implements Saveable {
p.enter(this);
}
+
+ private static Hash NODE_HASH = new Hash() {
+ public String hash(Node node) {
+ return node.getNodeName();
+ }
+ };
+
private boolean makePending(BuildableItem p) {
// LOGGER.info("Making "+p.task+" pending"); // REMOVE
p.isPending = true;
diff --git a/core/src/main/java/hudson/model/Run.java b/core/src/main/java/hudson/model/Run.java
index bbeba83a78a4600206b0fbad12e4c9a1e122354b..3f30f31d9d29f66310e7991ce18131c860226d00 100644
--- a/core/src/main/java/hudson/model/Run.java
+++ b/core/src/main/java/hudson/model/Run.java
@@ -507,6 +507,11 @@ public abstract class Run ,RunT extends Run transientActions = new Vector();
+ private String description;
+
public LabelAtom(String name) {
super(name);
}
@@ -85,6 +85,9 @@ public class LabelAtom extends Label implements Saveable {
return escape(name);
}
+ @Override
+ public boolean isAtom() { return true; }
+
/**
* {@inheritDoc}
*
@@ -106,33 +109,24 @@ public class LabelAtom extends Label implements Saveable {
protected void updateTransientActions() {
Vector ta = new Vector();
- // add the config link
- if (!getApplicablePropertyDescriptors().isEmpty()) {
- // if there's no property descriptor, there's nothing interesting to configure.
- ta.add(new Action() {
- public String getIconFileName() {
- if (Jenkins.getInstance().hasPermission(Jenkins.ADMINISTER))
- return "setting.png";
- else
- return null;
- }
-
- public String getDisplayName() {
- return "Configure";
- }
-
- public String getUrlName() {
- return "configure";
- }
- });
- }
-
for (LabelAtomProperty p : properties)
ta.addAll(p.getActions(this));
transientActions = ta;
}
+ /**
+ * @since TODO
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) throws IOException {
+ this.description = description;
+ save();
+ }
+
/**
* Properties associated with this label.
*/
@@ -210,11 +204,25 @@ public class LabelAtom extends Label implements Saveable {
app.checkPermission(Jenkins.ADMINISTER);
properties.rebuild(req, req.getSubmittedForm(), getApplicablePropertyDescriptors());
+
+ this.description = req.getSubmittedForm().getString("description");
+
updateTransientActions();
save();
- // take the user back to the label top page.
- rsp.sendRedirect2(".");
+ FormApply.success(".").generateResponse(req, rsp, null);
+ }
+
+ /**
+ * Accepts the new description.
+ */
+ @RequirePOST
+ @Restricted(DoNotUse.class)
+ public synchronized void doSubmitDescription( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
+ Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER);
+
+ setDescription(req.getParameter("description"));
+ rsp.sendRedirect("."); // go to the top page
}
/**
diff --git a/core/src/main/java/hudson/model/listeners/SCMListener.java b/core/src/main/java/hudson/model/listeners/SCMListener.java
index e9c9713c04b6cb48adefc66d3ce1eb028922b8ab..3f570aa24fb2ad361a992328a11d234d3f1b4e2d 100644
--- a/core/src/main/java/hudson/model/listeners/SCMListener.java
+++ b/core/src/main/java/hudson/model/listeners/SCMListener.java
@@ -116,7 +116,9 @@ public abstract class SCMListener implements ExtensionPoint {
@Deprecated
public void onChangeLogParsed(AbstractBuild,?> build, BuildListener listener, ChangeLogSet> changelog) throws Exception {
- onChangeLogParsed((Run) build, build.getProject().getScm(), listener, changelog);
+ if (Util.isOverridden(SCMListener.class, getClass(), "onChangeLogParsed", Run.class, SCM.class, TaskListener.class, ChangeLogSet.class)) {
+ onChangeLogParsed((Run) build, build.getProject().getScm(), listener, changelog);
+ }
}
/**
diff --git a/core/src/main/java/hudson/slaves/ChannelPinger.java b/core/src/main/java/hudson/slaves/ChannelPinger.java
index 4141af49b82eda4859c4646b5a222663fb545ef1..1e3837a96c37f4f40178be9b3d59217a14cc8d03 100644
--- a/core/src/main/java/hudson/slaves/ChannelPinger.java
+++ b/core/src/main/java/hudson/slaves/ChannelPinger.java
@@ -68,6 +68,10 @@ public class ChannelPinger extends ComputerListener {
@Override
public void preOnline(Computer c, Channel channel, FilePath root, TaskListener listener) {
+ install(channel);
+ }
+
+ public void install(Channel channel) {
if (pingInterval < 1) {
LOGGER.fine("Slave ping is disabled");
return;
@@ -75,9 +79,9 @@ public class ChannelPinger extends ComputerListener {
try {
channel.call(new SetUpRemotePing(pingInterval));
- LOGGER.fine("Set up a remote ping for " + c.getName());
+ LOGGER.fine("Set up a remote ping for " + channel.getName());
} catch (Exception e) {
- LOGGER.severe("Failed to set up a ping for " + c.getName());
+ LOGGER.severe("Failed to set up a ping for " + channel.getName());
}
// set up ping from both directions, so that in case of a router dropping a connection,
diff --git a/core/src/main/java/hudson/slaves/WorkspaceList.java b/core/src/main/java/hudson/slaves/WorkspaceList.java
index b6dd917da314deb180d7f025cb54a9cbf0c70d3a..5e335f23e26c1f60c808126ecc404f8ac4e381fa 100644
--- a/core/src/main/java/hudson/slaves/WorkspaceList.java
+++ b/core/src/main/java/hudson/slaves/WorkspaceList.java
@@ -32,6 +32,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.annotation.Nonnull;
/**
* Used by {@link Computer} to keep track of workspaces that are actively in use.
@@ -72,7 +73,7 @@ public final class WorkspaceList {
*/
public final boolean quick;
- public final FilePath path;
+ public final @Nonnull FilePath path;
/**
* Multiple threads can acquire the same lock if they share the same context object.
@@ -81,11 +82,11 @@ public final class WorkspaceList {
public int lockCount=1;
- private Entry(FilePath path, boolean quick) {
+ private Entry(@Nonnull FilePath path, boolean quick) {
this(path,quick,new Object()); // unique context
}
- private Entry(FilePath path, boolean quick, Object context) {
+ private Entry(@Nonnull FilePath path, boolean quick, Object context) {
this.path = path;
this.quick = quick;
this.context = context;
@@ -104,9 +105,10 @@ public final class WorkspaceList {
* Represents a leased workspace that needs to be returned later.
*/
public static abstract class Lease {
- public final FilePath path;
+ public final @Nonnull FilePath path;
- protected Lease(FilePath path) {
+ protected Lease(@Nonnull FilePath path) {
+ path.getRemote(); // null check
this.path = path;
}
@@ -118,7 +120,7 @@ public final class WorkspaceList {
/**
* Creates a dummy {@link Lease} object that does no-op in the release.
*/
- public static Lease createDummyLease(FilePath p) {
+ public static Lease createDummyLease(@Nonnull FilePath p) {
return new Lease(p) {
public void release() {
// noop
@@ -130,7 +132,7 @@ public final class WorkspaceList {
* Creates a {@link Lease} object that points to the specified path, but the lock
* is controlled by the given parent lease object.
*/
- public static Lease createLinkedDummyLease(FilePath p, final Lease parent) {
+ public static Lease createLinkedDummyLease(@Nonnull FilePath p, final Lease parent) {
return new Lease(p) {
public void release() {
parent.release();
@@ -151,7 +153,7 @@ public final class WorkspaceList {
* This method doesn't block prolonged amount of time. Whenever a desired workspace
* is in use, the unique variation is added.
*/
- public synchronized Lease allocate(FilePath base) throws InterruptedException {
+ public synchronized Lease allocate(@Nonnull FilePath base) throws InterruptedException {
return allocate(base,new Object());
}
@@ -162,7 +164,7 @@ public final class WorkspaceList {
* Threads that share the same context can re-acquire the same lock (which will just increment the lock count.)
* This allows related executors to share the same workspace.
*/
- public synchronized Lease allocate(FilePath base, Object context) throws InterruptedException {
+ public synchronized Lease allocate(@Nonnull FilePath base, Object context) throws InterruptedException {
for (int i=1; ; i++) {
FilePath candidate = i==1 ? base : base.withSuffix(COMBINATOR+i);
Entry e = inUse.get(candidate);
@@ -175,7 +177,7 @@ public final class WorkspaceList {
/**
* Just record that this workspace is being used, without paying any attention to the synchronization support.
*/
- public synchronized Lease record(FilePath p) {
+ public synchronized Lease record(@Nonnull FilePath p) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "recorded " + p, new Throwable("from " + this));
}
@@ -188,7 +190,7 @@ public final class WorkspaceList {
/**
* Releases an allocated or acquired workspace.
*/
- private synchronized void _release(FilePath p) {
+ private synchronized void _release(@Nonnull FilePath p) {
Entry old = inUse.get(p);
if (old==null)
throw new AssertionError("Releasing unallocated workspace "+p);
@@ -207,7 +209,7 @@ public final class WorkspaceList {
* @return
* The same {@link FilePath} as given to this method.
*/
- public synchronized Lease acquire(FilePath p) throws InterruptedException {
+ public synchronized Lease acquire(@Nonnull FilePath p) throws InterruptedException {
return acquire(p,false);
}
@@ -218,7 +220,7 @@ public final class WorkspaceList {
* If true, indicates that the acquired workspace will be returned quickly.
* This makes other calls to {@link #allocate(FilePath)} to wait for the release of this workspace.
*/
- public synchronized Lease acquire(FilePath p, boolean quick) throws InterruptedException {
+ public synchronized Lease acquire(@Nonnull FilePath p, boolean quick) throws InterruptedException {
return acquire(p,quick,new Object());
}
@@ -229,7 +231,7 @@ public final class WorkspaceList {
* Threads that share the same context can re-acquire the same lock (which will just increment the lock count.)
* This allows related executors to share the same workspace.
*/
- public synchronized Lease acquire(FilePath p, boolean quick, Object context) throws InterruptedException {
+ public synchronized Lease acquire(@Nonnull FilePath p, boolean quick, Object context) throws InterruptedException {
Entry e;
Thread t = Thread.currentThread();
@@ -257,7 +259,7 @@ public final class WorkspaceList {
/**
* Wraps a path into a valid lease.
*/
- private Lease lease(FilePath p) {
+ private Lease lease(@Nonnull FilePath p) {
return new Lease(p) {
public void release() {
_release(path);
diff --git a/core/src/main/java/hudson/util/ConsistentHash.java b/core/src/main/java/hudson/util/ConsistentHash.java
index 4878305fab94406df492e371946add439356137b..83bdb3f53d27ae8283606a93698ebb0400f2d8c4 100644
--- a/core/src/main/java/hudson/util/ConsistentHash.java
+++ b/core/src/main/java/hudson/util/ConsistentHash.java
@@ -48,7 +48,7 @@ import hudson.util.Iterators.DuplicateFilterIterator;
* and then we use MD5 to create random enough distribution.
*
*
- * This consistent hash implementaiton is consistent both to the addition/removal of Ts, as well
+ * This consistent hash implementation is consistent both to the addition/removal of Ts, as well
* as increase/decrease of the replicas.
*
*
@@ -186,7 +186,7 @@ public class ConsistentHash {
String hash(T t);
}
- private static final Hash DEFAULT_HASH = new Hash() {
+ static final Hash DEFAULT_HASH = new Hash() {
public String hash(Object o) {
return o.toString();
}
@@ -201,13 +201,13 @@ public class ConsistentHash {
}
public ConsistentHash(Hash hash) {
- this(hash,100);
+ this(hash, 100);
}
public ConsistentHash(Hash hash, int defaultReplication) {
this.hash = hash;
this.defaultReplication = defaultReplication;
- this.table = new Table(); // initial empty table
+ refreshTable();
}
public int countAllPoints() {
@@ -229,7 +229,8 @@ public class ConsistentHash {
*/
public void addAll(T... nodes) {
for (T node : nodes)
- add(node);
+ addInternal(node,defaultReplication);
+ refreshTable();
}
/**
@@ -237,14 +238,24 @@ public class ConsistentHash {
*/
public void addAll(Collection extends T> nodes) {
for (T node : nodes)
- add(node);
+ addInternal(node,defaultReplication);
+ refreshTable();
+ }
+
+ /**
+ * Calls {@link #add(Object,int)} with all the arguments.
+ */
+ public void addAll(Map extends T,Integer> nodes) {
+ for (Map.Entry extends T,Integer> node : nodes.entrySet())
+ addInternal(node.getKey(),node.getValue());
+ refreshTable();
}
/**
* Removes the node entirely. This is the same as {@code add(node,0)}
*/
public void remove(T node) {
- add(node,0);
+ add(node, 0);
}
/**
@@ -254,6 +265,11 @@ public class ConsistentHash {
* This is the only function that manipulates {@link #items}.
*/
public synchronized void add(T node, int replica) {
+ addInternal(node, replica);
+ refreshTable();
+ }
+
+ private void addInternal(T node, int replica) {
if(replica==0) {
items.remove(node);
} else {
@@ -263,9 +279,13 @@ public class ConsistentHash {
points[i] = new Point(md5(seed+':'+i),node);
items.put(node,points);
}
+ }
+
+ private void refreshTable() {
table = new Table();
}
+
/**
* Compresses a string into an integer with MD5.
*/
@@ -314,8 +334,8 @@ public class ConsistentHash {
* Creates a permutation of all the nodes for the given data point.
*
*
- * The returned pemutation is consistent, in the sense that small change
- * to the consitent hash (like addition/removal/change of replicas) only
+ * The returned permutation is consistent, in the sense that small change
+ * to the consistent hash (like addition/removal/change of replicas) only
* creates a small change in the permutation.
*
*
diff --git a/core/src/main/java/jenkins/diagnosis/HsErrPidList.java b/core/src/main/java/jenkins/diagnosis/HsErrPidList.java
index 00c8af5d06e26a43615b9dc96408e378799f6759..e8309414489d9ebe13b422ea2624cb5ac3367798 100644
--- a/core/src/main/java/jenkins/diagnosis/HsErrPidList.java
+++ b/core/src/main/java/jenkins/diagnosis/HsErrPidList.java
@@ -30,7 +30,7 @@ import org.apache.commons.io.IOUtils;
*
* @author Kohsuke Kawaguchi
*/
-@Extension(optional=true)
+@Extension(optional=true) // TODO why would an extension using a built-in extension point need to be marked optional?
public class HsErrPidList extends AdministrativeMonitor {
/**
* hs_err_pid files that we think belong to us.
@@ -43,6 +43,9 @@ public class HsErrPidList extends AdministrativeMonitor {
private MappedByteBuffer map;
public HsErrPidList() {
+ if (Functions.getIsUnitTest()) {
+ return;
+ }
try {
FileChannel ch = new FileInputStream(getSecretKeyFile()).getChannel();
map = ch.map(MapMode.READ_ONLY,0,1);
diff --git a/core/src/main/java/jenkins/model/Jenkins.java b/core/src/main/java/jenkins/model/Jenkins.java
index 419c4c528a636f003463980679d1b4ef23b59e48..415e037f95bc81e4dc8ab4934a5af5f5c5b80ba4 100644
--- a/core/src/main/java/jenkins/model/Jenkins.java
+++ b/core/src/main/java/jenkins/model/Jenkins.java
@@ -2014,6 +2014,11 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
return buildsDir;
}
+ @Restricted(NoExternalUse.class)
+ public void setRawBuildsDir(String buildsDir) {
+ this.buildsDir = buildsDir;
+ }
+
public FilePath getRootPath() {
return new FilePath(getRootDir());
}
@@ -2307,7 +2312,7 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
*
* Note that the look up is case-insensitive.
*/
- public TopLevelItem getItem(String name) {
+ @Override public TopLevelItem getItem(String name) throws AccessDeniedException {
if (name==null) return null;
TopLevelItem item = items.get(name);
if (item==null)
@@ -2411,8 +2416,9 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
* @return
* null if either such {@link Item} doesn't exist under the given full name,
* or it exists but it's no an instance of the given type.
+ * @throws AccessDeniedException as per {@link ItemGroup#getItem}
*/
- public @CheckForNull T getItemByFullName(String fullName, Class type) {
+ public @CheckForNull T getItemByFullName(String fullName, Class type) throws AccessDeniedException {
StringTokenizer tokens = new StringTokenizer(fullName,"/");
ItemGroup parent = this;
diff --git a/core/src/main/java/jenkins/security/FrameOptionsPageDecorator.java b/core/src/main/java/jenkins/security/FrameOptionsPageDecorator.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc47e231b56c28effaf9e66c018500bb83377479
--- /dev/null
+++ b/core/src/main/java/jenkins/security/FrameOptionsPageDecorator.java
@@ -0,0 +1,17 @@
+package jenkins.security;
+
+import hudson.Extension;
+import hudson.model.PageDecorator;
+import org.kohsuke.accmod.Restricted;
+import org.kohsuke.accmod.restrictions.NoExternalUse;
+
+/**
+ * Adds the 'X-Frame-Options' header to all web pages.
+ *
+ * @since 1.581
+ */
+@Extension(ordinal = 1000)
+public class FrameOptionsPageDecorator extends PageDecorator {
+ @Restricted(NoExternalUse.class)
+ public static boolean enabled = Boolean.valueOf(System.getProperty(FrameOptionsPageDecorator.class.getName() + ".enabled", "true"));
+}
diff --git a/core/src/main/java/jenkins/widgets/RunListProgressiveRendering.java b/core/src/main/java/jenkins/widgets/RunListProgressiveRendering.java
index 5ab72a8a38eb2af4d3001058e443dcbdc1cd5972..b7ec216f1ac4a3b48692e41d5bcdc797f1c7f5b0 100644
--- a/core/src/main/java/jenkins/widgets/RunListProgressiveRendering.java
+++ b/core/src/main/java/jenkins/widgets/RunListProgressiveRendering.java
@@ -63,7 +63,7 @@ public abstract class RunListProgressiveRendering extends ProgressiveRendering {
}
JSONObject element = new JSONObject();
calculate(build, element);
- synchronized (results) {
+ synchronized (this) {
results.add(element);
}
decay *= (1 - 1 / MAX_LIKELY_RUNS);
diff --git a/core/src/main/resources/hudson/model/AbstractModelObject/descriptionForm.jelly b/core/src/main/resources/hudson/model/AbstractModelObject/descriptionForm.jelly
index e0259987ffada085c62be2c248e9ca41eb58068e..9891f09a181b02eb1126fa77405528db31069471 100644
--- a/core/src/main/resources/hudson/model/AbstractModelObject/descriptionForm.jelly
+++ b/core/src/main/resources/hudson/model/AbstractModelObject/descriptionForm.jelly
@@ -27,8 +27,8 @@ THE SOFTWARE.
-->
-
-
+
+