org.kohsuke
diff --git a/core/src/main/java/hudson/ClassicPluginStrategy.java b/core/src/main/java/hudson/ClassicPluginStrategy.java
index 7f62a9e244e2..a7f3259bb525 100644
--- a/core/src/main/java/hudson/ClassicPluginStrategy.java
+++ b/core/src/main/java/hudson/ClassicPluginStrategy.java
@@ -641,9 +641,7 @@ protected Class> findClass(String name) throws ClassNotFoundException {
if (PluginManager.FAST_LOOKUP) {
for (PluginWrapper pw : getTransitiveDependencies()) {
try {
- Class> c = ClassLoaderReflectionToolkit._findLoadedClass(pw.classLoader, name);
- if (c!=null) return c;
- return ClassLoaderReflectionToolkit._findClass(pw.classLoader, name);
+ return ClassLoaderReflectionToolkit.loadClass(pw.classLoader, name);
} catch (ClassNotFoundException ignored) {
//not found. try next
}
diff --git a/core/src/main/java/hudson/PluginManager.java b/core/src/main/java/hudson/PluginManager.java
index 47bb91c8ed14..1d780278df5b 100644
--- a/core/src/main/java/hudson/PluginManager.java
+++ b/core/src/main/java/hudson/PluginManager.java
@@ -2197,15 +2197,7 @@ protected Class> findClass(String name) throws ClassNotFoundException {
if (FAST_LOOKUP) {
for (PluginWrapper p : activePlugins) {
try {
- Class> c = ClassLoaderReflectionToolkit._findLoadedClass(p.classLoader, name);
- if (c != null) {
- synchronized (loaded) {
- loaded.put(name, c);
- }
- return c;
- }
- // calling findClass twice appears to cause LinkageError: duplicate class def
- c = ClassLoaderReflectionToolkit._findClass(p.classLoader, name);
+ Class> c = ClassLoaderReflectionToolkit.loadClass(p.classLoader, name);
synchronized (loaded) {
loaded.put(name, c);
}
diff --git a/core/src/main/java/jenkins/ClassLoaderReflectionToolkit.java b/core/src/main/java/jenkins/ClassLoaderReflectionToolkit.java
index 42b013452249..edce6b431a00 100644
--- a/core/src/main/java/jenkins/ClassLoaderReflectionToolkit.java
+++ b/core/src/main/java/jenkins/ClassLoaderReflectionToolkit.java
@@ -70,6 +70,7 @@ private static class GetClassLoadingLock {
/**
* Calls {@link ClassLoader#findLoadedClass} while holding {@link ClassLoader#getClassLoadingLock}.
* @since 1.553
+ * @deprecated use {@link #loadClass(ClassLoader, String)}
*/
public static @CheckForNull Class> _findLoadedClass(ClassLoader cl, String name) {
synchronized (getClassLoadingLock(cl, name)) {
@@ -100,6 +101,7 @@ private static class FindLoadedClass {
/**
* Calls {@link ClassLoader#findClass} while holding {@link ClassLoader#getClassLoadingLock}.
* @since 1.553
+ * @deprecated use {@link #loadClass(ClassLoader, String)}
*/
public static @NonNull Class> _findClass(ClassLoader cl, String name) throws ClassNotFoundException {
synchronized (getClassLoadingLock(cl, name)) {
@@ -124,6 +126,48 @@ private static class FindClass {
}
}
+ /**
+ * Load the class with the specified binary name. This method searches for classes in the
+ * following order:
+ *
+ *
+ * -
+ *
Invoke {@link ClassLoader#findLoadedClass(String)} to check if the class has already
+ * been loaded.
+ *
-
+ *
Invoke the {@link ClassLoader#findClass(String)} method to find the class.
+ *
+ *
+ * This method synchronizes on the result of {@link ClassLoader#getClassLoadingLock(String)}
+ * during the entire class loading process.
+ *
+ * @param cl The {@link ClassLoader} to use.
+ * @param name The binary name of the class.
+ * @return The resulting {@link Class} object.
+ * @throws ClassNotFoundException If the class could not be found.
+ * @since 2.TODO
+ */
+ public static @NonNull Class> loadClass(ClassLoader cl, String name) throws ClassNotFoundException {
+ synchronized (getClassLoadingLock(cl, name)) {
+ // First, check if the class has already been loaded.
+ Class> c;
+ if (cl instanceof JenkinsClassLoader) {
+ c = ((JenkinsClassLoader) cl).findLoadedClass2(name);
+ } else {
+ c = (Class) invoke(FindLoadedClass.FIND_LOADED_CLASS, RuntimeException.class, cl, name);
+ }
+ if (c != null) {
+ return c;
+ }
+
+ // Find the class.
+ if (cl instanceof JenkinsClassLoader) {
+ return ((JenkinsClassLoader) cl).findClass(name);
+ } else {
+ return (Class) invoke(FindClass.FIND_CLASS, ClassNotFoundException.class, cl, name);
+ }
+ }
+ }
/**
* Calls {@link ClassLoader#findResource}.
diff --git a/core/src/main/java/jenkins/ProxyInjector.java b/core/src/main/java/jenkins/ProxyInjector.java
index 3736b32b08aa..fad1d24680ae 100644
--- a/core/src/main/java/jenkins/ProxyInjector.java
+++ b/core/src/main/java/jenkins/ProxyInjector.java
@@ -31,6 +31,8 @@
import com.google.inject.Provider;
import com.google.inject.Scope;
import com.google.inject.TypeLiteral;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.TypeConverterBinding;
import java.lang.annotation.Annotation;
import java.util.List;
@@ -134,4 +136,14 @@ public Map, Scope> getScopeBindings() {
public Set getTypeConverterBindings() {
return resolve().getTypeConverterBindings();
}
+
+ @Override
+ public List getElements() {
+ return resolve().getElements();
+ }
+
+ @Override
+ public Map, List> getAllMembersInjectorInjectionPoints() {
+ return resolve().getAllMembersInjectorInjectionPoints();
+ }
}
diff --git a/core/src/main/java/jenkins/model/InterruptedBuildAction.java b/core/src/main/java/jenkins/model/InterruptedBuildAction.java
index 9bcfefc17a8c..f67088a54044 100644
--- a/core/src/main/java/jenkins/model/InterruptedBuildAction.java
+++ b/core/src/main/java/jenkins/model/InterruptedBuildAction.java
@@ -43,11 +43,11 @@ public class InterruptedBuildAction extends InvisibleAction {
private final List causes;
public InterruptedBuildAction(Collection extends CauseOfInterruption> causes) {
- this.causes = Collections.unmodifiableList(new ArrayList<>(causes));
+ this.causes = new ArrayList<>(causes);
}
@Exported
public List getCauses() {
- return causes;
+ return Collections.unmodifiableList(causes);
}
}
diff --git a/core/src/main/java/jenkins/model/Jenkins.java b/core/src/main/java/jenkins/model/Jenkins.java
index 86a5d4030715..6a46ec37db3e 100644
--- a/core/src/main/java/jenkins/model/Jenkins.java
+++ b/core/src/main/java/jenkins/model/Jenkins.java
@@ -2239,14 +2239,38 @@ public DescribableList, NodePropertyDescriptor> getGlobalNodePro
* but we also call this periodically to self-heal any data out-of-sync issue.
*/
/*package*/ void trimLabels() {
+ trimLabels((Set) null);
+ }
+
+ /**
+ * Reset labels and remove invalid ones for the given nodes.
+ * @param nodes the nodes taken as reference to update labels
+ */
+ void trimLabels(Node... nodes) {
+ Set includedLabels = new HashSet<>();
+ Arrays.asList(nodes).stream().filter(Objects::nonNull).forEach(n -> includedLabels.addAll(n.getAssignedLabels()));
+ trimLabels(includedLabels);
+ }
+
+ /**
+ * Reset labels and remove invalid ones for the given nodes.
+ * @param includedLabels the labels taken as reference to update labels. If {@code null}, all labels are considered.
+ */
+ private void trimLabels(@CheckForNull Set includedLabels) {
Set