type, Hudson hudson)
* from here.
*
*
- * See https://bugs.openjdk.java.net/browse/JDK-4993813 for how to force a class initialization.
- * Also see http://kohsuke.org/2010/09/01/deadlock-that-you-cant-avoid/ for how class initialization
+ * See JDK-4993813 for how to force a class initialization.
+ * Also see this blog post for how class initialization
* can results in a dead lock.
*/
public void scout(Class extensionType, Hudson hudson) {
@@ -560,7 +560,7 @@ protected void configure() {
}
public List> getLoadedIndex() {
- return Collections.unmodifiableList(new ArrayList<>(loadedIndex));
+ return List.copyOf(loadedIndex);
}
@Override
@@ -645,7 +645,7 @@ private List> getIndices() {
// 5. dead lock
if (indices == null) {
ClassLoader cl = Jenkins.get().getPluginManager().uberClassLoader;
- indices = Collections.unmodifiableList(StreamSupport.stream(Index.load(Extension.class, Object.class, cl).spliterator(), false).collect(Collectors.toList()));
+ indices = StreamSupport.stream(Index.load(Extension.class, Object.class, cl).spliterator(), false).collect(Collectors.toUnmodifiableList());
}
return indices;
}
diff --git a/core/src/main/java/hudson/ExtensionList.java b/core/src/main/java/hudson/ExtensionList.java
index 7bae8ff5d83b..090d2172ca66 100644
--- a/core/src/main/java/hudson/ExtensionList.java
+++ b/core/src/main/java/hudson/ExtensionList.java
@@ -169,7 +169,7 @@ public void addListener(@NonNull ExtensionListListener listener) {
@Override
public @NonNull Iterator iterator() {
// we need to intercept mutation, so for now don't allow Iterator.remove
- return new AdaptedIterator, T>(Iterators.readOnly(ensureLoaded().iterator())) {
+ return new AdaptedIterator<>(Iterators.readOnly(ensureLoaded().iterator())) {
@Override
protected T adapt(ExtensionComponent item) {
return item.getInstance();
@@ -198,7 +198,7 @@ public int size() {
* Gets the read-only view of this {@link ExtensionList} where components are reversed.
*/
public List reverseView() {
- return new AbstractList() {
+ return new AbstractList<>() {
@Override
public T get(int index) {
return ExtensionList.this.get(size() - index - 1);
diff --git a/core/src/main/java/hudson/ExtensionListView.java b/core/src/main/java/hudson/ExtensionListView.java
index 0127752e46bd..2b10152b5c0f 100644
--- a/core/src/main/java/hudson/ExtensionListView.java
+++ b/core/src/main/java/hudson/ExtensionListView.java
@@ -56,7 +56,7 @@ public class ExtensionListView {
* Creates a plain {@link List} backed by the current {@link ExtensionList}.
*/
public static List createList(final Class type) {
- return new AbstractList() {
+ return new AbstractList<>() {
private ExtensionList storage() {
return Jenkins.get().getExtensionList(type);
}
@@ -103,7 +103,7 @@ public boolean remove(Object o) {
* Creates a seriously hacked up {@link CopyOnWriteList} that acts as a view to the current {@link ExtensionList}.
*/
public static CopyOnWriteList createCopyOnWriteList(final Class type) {
- return new CopyOnWriteList() {
+ return new CopyOnWriteList<>() {
private ExtensionList storage() {
return Jenkins.get().getExtensionList(type);
}
diff --git a/core/src/main/java/hudson/FilePath.java b/core/src/main/java/hudson/FilePath.java
index 6b22e21d8362..60c213b7e03f 100644
--- a/core/src/main/java/hudson/FilePath.java
+++ b/core/src/main/java/hudson/FilePath.java
@@ -532,13 +532,10 @@ private static class Archive extends MasterToSlaveFileCallable {
@Override
public Integer invoke(File f, VirtualChannel channel) throws IOException {
- Archiver a = factory.create(out);
- try {
+ try (Archiver a = factory.create(out)) {
scanner.scan(f, ignoringSymlinks(a, verificationRoot, noFollowLinks));
- } finally {
- a.close();
+ return a.countEntries();
}
- return a.countEntries();
}
private static final long serialVersionUID = 1L;
@@ -708,10 +705,9 @@ private static void unzip(File dir, InputStream in) throws IOException {
private static void unzip(File dir, File zipFile) throws IOException {
dir = dir.getAbsoluteFile(); // without absolutization, getParentFile below seems to fail
- ZipFile zip = new ZipFile(zipFile);
- Enumeration entries = zip.getEntries();
- try {
+ try (ZipFile zip = new ZipFile(zipFile)) {
+ Enumeration entries = zip.getEntries();
while (entries.hasMoreElements()) {
ZipEntry e = entries.nextElement();
File f = new File(dir, e.getName());
@@ -740,8 +736,6 @@ private static void unzip(File dir, File zipFile) throws IOException {
Files.setLastModifiedTime(Util.fileToPath(f), e.getLastModifiedTime());
}
}
- } finally {
- zip.close();
}
}
@@ -922,11 +916,9 @@ public OutputStream compress(OutputStream out) throws IOException {
* @since 1.292
*/
public void untarFrom(InputStream _in, final TarCompression compression) throws IOException, InterruptedException {
- try {
+ try (_in) {
final InputStream in = new RemoteInputStream(_in, Flag.GREEDY);
act(new UntarFrom(compression, in));
- } finally {
- _in.close();
}
}
@@ -2382,7 +2374,7 @@ private static class ReadToString extends MasterToSlaveFileCallable {
@Override
public String invoke(File f, VirtualChannel channel) throws IOException, InterruptedException {
- return new String(Files.readAllBytes(fileToPath(f)), Charset.defaultCharset());
+ return Files.readString(fileToPath(f), Charset.defaultCharset());
}
}
@@ -2947,10 +2939,8 @@ public int tar(OutputStream out, DirScanner scanner) throws IOException, Interru
*/
private static Integer writeToTar(File baseDir, DirScanner scanner, OutputStream out) throws IOException {
Archiver tw = ArchiverFactory.TAR.create(out);
- try {
+ try (tw) {
scanner.scan(baseDir, tw);
- } finally {
- tw.close();
}
return tw.countEntries();
}
diff --git a/core/src/main/java/hudson/Functions.java b/core/src/main/java/hudson/Functions.java
index a67bf746c3b8..92b158a1efa6 100644
--- a/core/src/main/java/hudson/Functions.java
+++ b/core/src/main/java/hudson/Functions.java
@@ -100,7 +100,6 @@
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
import java.lang.management.LockInfo;
import java.lang.management.ManagementFactory;
import java.lang.management.MonitorInfo;
@@ -747,10 +746,7 @@ public static String appendSpaceIfNotNull(String n) {
public static String nbspIndent(String size) {
int i = size.indexOf('x');
i = Integer.parseInt(i > 0 ? size.substring(0, i) : size) / 10;
- StringBuilder buf = new StringBuilder(30);
- for (int j = 2; j <= i; j++)
- buf.append(" ");
- return buf.toString();
+ return " ".repeat(Math.max(0, i - 1));
}
public static String getWin32ErrorMessage(IOException e) {
@@ -777,11 +773,7 @@ public static String urlEncode(String s) {
if (s == null) {
return "";
}
- try {
- return URLEncoder.encode(s, StandardCharsets.UTF_8.name());
- } catch (UnsupportedEncodingException e) {
- throw new Error(e); // impossible
- }
+ return URLEncoder.encode(s, StandardCharsets.UTF_8);
}
public static String escape(String s) {
@@ -1853,7 +1845,7 @@ public static String joinPath(String... components) {
/**
* Escapes the character unsafe for e-mail address.
- * See http://en.wikipedia.org/wiki/E-mail_address for the details,
+ * See the Wikipedia page for the details,
* but here the vocabulary is even more restricted.
*/
public static String toEmailSafeString(String projectName) {
@@ -1933,19 +1925,26 @@ public void calcCheckUrl(Map attributes, String userDefined, Object descriptor,
*
* Used in {@code task.jelly} to decide if the page should be highlighted.
*/
- public boolean hyperlinkMatchesCurrentPage(String href) throws UnsupportedEncodingException {
+ public boolean hyperlinkMatchesCurrentPage(String href) {
String url = Stapler.getCurrentRequest().getRequestURL().toString();
if (href == null || href.length() <= 1) return ".".equals(href) && url.endsWith("/");
- url = URLDecoder.decode(url, "UTF-8");
- href = URLDecoder.decode(href, "UTF-8");
+ url = URLDecoder.decode(url, StandardCharsets.UTF_8);
+ href = URLDecoder.decode(href, StandardCharsets.UTF_8);
if (url.endsWith("/")) url = url.substring(0, url.length() - 1);
if (href.endsWith("/")) href = href.substring(0, href.length() - 1);
return url.endsWith(href);
}
+ /**
+ * @deprecated From JEXL expressions ({@code ${…}}) in {@code *.jelly} files
+ * you can use {@code [obj]} syntax to construct an {@code Object[]}
+ * (which may be usable where a {@link List} is expected)
+ * rather than {@code h.singletonList(obj)}.
+ */
+ @Deprecated
public List singletonList(T t) {
- return Collections.singletonList(t);
+ return List.of(t);
}
/**
@@ -2360,33 +2359,34 @@ public static String tryGetIconPath(String iconGuess, JellyContext context) {
}
StaplerRequest currentRequest = Stapler.getCurrentRequest();
- currentRequest.getWebApp().getDispatchValidator().allowDispatch(currentRequest, Stapler.getCurrentResponse());
String rootURL = currentRequest.getContextPath();
Icon iconMetadata = tryGetIcon(iconGuess);
- String iconSource = null;
+ String iconSource;
if (iconMetadata != null) {
- iconSource = iconMetadata.getQualifiedUrl(context);
+ iconSource = IconSet.tryTranslateTangoIconToSymbol(iconMetadata.getClassSpec(), () -> iconMetadata.getQualifiedUrl(context));
+ } else {
+ iconSource = guessIcon(iconGuess, rootURL);
}
+ return iconSource;
+ }
- if (iconMetadata == null) {
- //noinspection HttpUrlsUsage
- if (iconGuess.startsWith("http://") || iconGuess.startsWith("https://")) {
- return iconGuess;
- }
+ static String guessIcon(String iconGuess, String rootURL) {
+ String iconSource;
+ //noinspection HttpUrlsUsage
+ if (iconGuess.startsWith("http://") || iconGuess.startsWith("https://")) {
+ iconSource = iconGuess;
+ } else {
if (!iconGuess.startsWith("/")) {
iconGuess = "/" + iconGuess;
}
- iconSource = rootURL + (iconGuess.startsWith("/images/") || iconGuess.startsWith("/plugin/") ? getResourcePath() : "") + iconGuess;
- }
-
- if (iconMetadata != null && iconMetadata.getClassSpec() != null) {
- String translatedIcon = IconSet.tryTranslateTangoIconToSymbol(iconMetadata.getClassSpec());
- if (translatedIcon != null) {
- return translatedIcon;
+ if (iconGuess.startsWith(rootURL)) {
+ if ((!rootURL.equals("/images") && !rootURL.equals("/plugin")) || iconGuess.startsWith(rootURL + rootURL)) {
+ iconGuess = iconGuess.substring(rootURL.length());
+ }
}
+ iconSource = rootURL + (iconGuess.startsWith("/images/") || iconGuess.startsWith("/plugin/") ? getResourcePath() : "") + iconGuess;
}
-
return iconSource;
}
diff --git a/core/src/main/java/hudson/PluginManager.java b/core/src/main/java/hudson/PluginManager.java
index c3cd3a750e6d..231a68a3de5b 100644
--- a/core/src/main/java/hudson/PluginManager.java
+++ b/core/src/main/java/hudson/PluginManager.java
@@ -187,6 +187,7 @@
* @author Kohsuke Kawaguchi
*/
@ExportedBean
+@SuppressFBWarnings(value = "THROWS_METHOD_THROWS_CLAUSE_BASIC_EXCEPTION", justification = "TODO needs triage")
public abstract class PluginManager extends AbstractModelObject implements OnMaster, StaplerOverridable, StaplerProxy {
/** Custom plugin manager system property or context param. */
public static final String CUSTOM_PLUGIN_MANAGER = PluginManager.class.getName() + ".className";
@@ -466,7 +467,7 @@ private boolean isDuplicate(PluginWrapper p) {
@Override
public void run(Reactor reactor) throws Exception {
try {
- CyclicGraphDetector cgd = new CyclicGraphDetector() {
+ CyclicGraphDetector cgd = new CyclicGraphDetector<>() {
@Override
protected List getEdges(PluginWrapper p) {
List next = new ArrayList<>();
@@ -929,7 +930,7 @@ public void dynamicLoad(File arc, boolean removeExisting, @CheckForNull List, ModelObject {
private final List optionalDependencies;
public List getDependencyErrors() {
- return Collections.unmodifiableList(new ArrayList<>(dependencyErrors.keySet()));
+ return List.copyOf(dependencyErrors.keySet());
}
@Restricted(NoExternalUse.class) // Jelly use
@@ -222,7 +222,7 @@ public boolean hasDerivedDependencyErrors() {
* The core can depend on a plugin if it is bundled. Sometimes it's the only thing that
* depends on the plugin e.g. UI support library bundle plugin.
*/
- private static Set CORE_ONLY_DEPENDANT = Collections.singleton("jenkins-core");
+ private static Set CORE_ONLY_DEPENDANT = Set.of("jenkins-core");
/**
* Set the list of components that depend on this plugin.
diff --git a/core/src/main/java/hudson/Proc.java b/core/src/main/java/hudson/Proc.java
index 6bcb6d416819..61defc264f54 100644
--- a/core/src/main/java/hudson/Proc.java
+++ b/core/src/main/java/hudson/Proc.java
@@ -320,12 +320,10 @@ public OutputStream getStdin() {
@Override
public int join() throws InterruptedException, IOException {
// show what we are waiting for in the thread title
- // since this involves some native work, let's have some soak period before enabling this by default
Thread t = Thread.currentThread();
String oldName = t.getName();
if (SHOW_PID) {
- ProcessTree.OSProcess p = ProcessTree.get().get(proc);
- t.setName(oldName + " " + (p != null ? "waiting for pid=" + p.getPid() : "waiting for " + name));
+ t.setName(oldName + " waiting for pid=" + proc.pid());
}
try {
@@ -506,7 +504,7 @@ public OutputStream getStdin() {
* Debug switch to have the thread display the process it's waiting for.
*/
@SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "for debugging")
- public static boolean SHOW_PID = false;
+ public static boolean SHOW_PID = true;
/**
* An instance of {@link Proc}, which has an internal workaround for JENKINS-23271.
diff --git a/core/src/main/java/hudson/StructuredForm.java b/core/src/main/java/hudson/StructuredForm.java
index 708d0120dc9d..286e79997652 100644
--- a/core/src/main/java/hudson/StructuredForm.java
+++ b/core/src/main/java/hudson/StructuredForm.java
@@ -33,7 +33,7 @@
/**
* Obtains the structured form data from {@link StaplerRequest}.
- * See https://www.jenkins.io/doc/developer/forms/structured-form-submission/
+ * See the developer documentation.
*
* @author Kohsuke Kawaguchi
*/
@@ -67,7 +67,7 @@ public static List toList(JSONObject parent, String propertyName) {
if (v == null)
return Collections.emptyList();
if (v instanceof JSONObject)
- return Collections.singletonList((JSONObject) v);
+ return List.of((JSONObject) v);
if (v instanceof JSONArray)
return (List) v;
diff --git a/core/src/main/java/hudson/TcpSlaveAgentListener.java b/core/src/main/java/hudson/TcpSlaveAgentListener.java
index eb6358f7a3f3..ddecdfa09651 100644
--- a/core/src/main/java/hudson/TcpSlaveAgentListener.java
+++ b/core/src/main/java/hudson/TcpSlaveAgentListener.java
@@ -313,7 +313,7 @@ public void run() {
* Primarily used to test the low-level connectivity.
*/
private void respondHello(String header, Socket s) throws IOException {
- try {
+ try (s) {
DataOutputStream out = new DataOutputStream(s.getOutputStream());
String response;
if (header.startsWith("GET / ")) {
@@ -336,8 +336,6 @@ private void respondHello(String header, Socket s) throws IOException {
InputStream i = s.getInputStream();
IOUtils.copy(i, NullOutputStream.NULL_OUTPUT_STREAM);
s.shutdownInput();
- } finally {
- s.close();
}
}
@@ -400,20 +398,18 @@ public String getDisplayName() {
@Override
public void handle(Socket socket) throws IOException, InterruptedException {
- try {
+ try (socket) {
try (OutputStream stream = socket.getOutputStream()) {
LOGGER.log(Level.FINE, "Received ping request from {0}", socket.getRemoteSocketAddress());
stream.write(ping);
stream.flush();
LOGGER.log(Level.FINE, "Sent ping response to {0}", socket.getRemoteSocketAddress());
}
- } finally {
- socket.close();
}
}
public boolean connect(Socket socket) throws IOException {
- try {
+ try (socket) {
LOGGER.log(Level.FINE, "Requesting ping from {0}", socket.getRemoteSocketAddress());
try (DataOutputStream out = new DataOutputStream(socket.getOutputStream())) {
out.writeUTF("Protocol:Ping");
@@ -435,8 +431,6 @@ public boolean connect(Socket socket) throws IOException {
}
}
}
- } finally {
- socket.close();
}
}
}
diff --git a/core/src/main/java/hudson/Util.java b/core/src/main/java/hudson/Util.java
index 6af39fc1cb75..51abbf86a1aa 100644
--- a/core/src/main/java/hudson/Util.java
+++ b/core/src/main/java/hudson/Util.java
@@ -625,7 +625,7 @@ public static String ensureEndsWith(@CheckForNull String subject, @CheckForNull
*/
@NonNull
public static String getDigestOf(@NonNull InputStream source) throws IOException {
- try {
+ try (source) {
MessageDigest md5 = getMd5();
DigestInputStream in = new DigestInputStream(source, md5);
// Note: IOUtils.copy() buffers the input internally, so there is no
@@ -634,8 +634,6 @@ public static String getDigestOf(@NonNull InputStream source) throws IOException
return toHexString(md5.digest());
} catch (NoSuchAlgorithmException e) {
throw new IOException("MD5 not installed", e); // impossible
- } finally {
- source.close();
}
/* JENKINS-18178: confuses Maven 2 runner
try {
diff --git a/core/src/main/java/hudson/WebAppMain.java b/core/src/main/java/hudson/WebAppMain.java
index c63e1f813a96..99603ac1e411 100644
--- a/core/src/main/java/hudson/WebAppMain.java
+++ b/core/src/main/java/hudson/WebAppMain.java
@@ -140,10 +140,10 @@ public void contextInitialized(ServletContextEvent event) {
// Nicer console log formatting when using mvn jetty:run.
if (Main.isDevelopmentMode && System.getProperty("java.util.logging.config.file") == null) {
try {
- Formatter formatter = (Formatter) Class.forName("io.jenkins.lib.support_log_formatter.SupportLogFormatter").newInstance();
+ Formatter formatter = (Formatter) Class.forName("io.jenkins.lib.support_log_formatter.SupportLogFormatter").getDeclaredConstructor().newInstance();
for (Handler h : Logger.getLogger("").getHandlers()) {
if (h instanceof ConsoleHandler) {
- ((ConsoleHandler) h).setFormatter(formatter);
+ h.setFormatter(formatter);
}
}
} catch (ClassNotFoundException x) {
diff --git a/core/src/main/java/hudson/cli/CLIAction.java b/core/src/main/java/hudson/cli/CLIAction.java
index 31d4700e4cb1..633ecca3437c 100644
--- a/core/src/main/java/hudson/cli/CLIAction.java
+++ b/core/src/main/java/hudson/cli/CLIAction.java
@@ -277,8 +277,8 @@ void run() throws IOException, InterruptedException {
wait();
}
}
- PrintStream stdout = new PrintStream(streamStdout(), false, encoding.name());
- PrintStream stderr = new PrintStream(streamStderr(), true, encoding.name());
+ PrintStream stdout = new PrintStream(streamStdout(), false, encoding);
+ PrintStream stderr = new PrintStream(streamStderr(), true, encoding);
if (args.isEmpty()) {
stderr.println("Connection closed before arguments received");
sendExit(2);
diff --git a/core/src/main/java/hudson/cli/CLICommand.java b/core/src/main/java/hudson/cli/CLICommand.java
index ab0a7266aec1..e779afbc3453 100644
--- a/core/src/main/java/hudson/cli/CLICommand.java
+++ b/core/src/main/java/hudson/cli/CLICommand.java
@@ -42,7 +42,6 @@
import java.io.InputStream;
import java.io.PrintStream;
import java.io.UncheckedIOException;
-import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
@@ -415,11 +414,7 @@ public final String getSingleLineSummary() {
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
- try {
- return out.toString(charset.name());
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError(e);
- }
+ return out.toString(charset);
}
/**
@@ -437,11 +432,7 @@ public final String getUsage() {
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
- try {
- return out.toString(charset.name());
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError(e);
- }
+ return out.toString(charset);
}
/**
@@ -458,20 +449,11 @@ public final String getLongDescription() {
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
- PrintStream ps;
- try {
- ps = new PrintStream(out, false, charset.name());
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError(e);
- }
+ PrintStream ps = new PrintStream(out, false, charset);
printUsageSummary(ps);
ps.close();
- try {
- return out.toString(charset.name());
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError(e);
- }
+ return out.toString(charset);
}
/**
diff --git a/core/src/main/java/hudson/cli/declarative/CLIRegisterer.java b/core/src/main/java/hudson/cli/declarative/CLIRegisterer.java
index 8b2f2348c577..5fdf42672fbf 100644
--- a/core/src/main/java/hudson/cli/declarative/CLIRegisterer.java
+++ b/core/src/main/java/hudson/cli/declarative/CLIRegisterer.java
@@ -27,6 +27,7 @@
import static java.util.logging.Level.SEVERE;
import edu.umd.cs.findbugs.annotations.NonNull;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.AbortException;
import hudson.Extension;
import hudson.ExtensionComponent;
@@ -71,6 +72,12 @@
* @author Kohsuke Kawaguchi
*/
@Extension
+@SuppressFBWarnings(
+ value = {
+ "THROWS_METHOD_THROWS_CLAUSE_BASIC_EXCEPTION",
+ "THROWS_METHOD_THROWS_RUNTIMEEXCEPTION"
+ },
+ justification = "TODO needs triage")
public class CLIRegisterer extends ExtensionFinder {
@Override
public ExtensionComponentSet refresh() throws ExtensionRefreshException {
diff --git a/core/src/main/java/hudson/console/ConsoleAnnotationOutputStream.java b/core/src/main/java/hudson/console/ConsoleAnnotationOutputStream.java
index d2ac95da65bd..256211a7267b 100644
--- a/core/src/main/java/hudson/console/ConsoleAnnotationOutputStream.java
+++ b/core/src/main/java/hudson/console/ConsoleAnnotationOutputStream.java
@@ -113,7 +113,7 @@ protected void eol(byte[] in, int sz) throws IOException {
if (a != null) {
if (annotators == null)
annotators = new ArrayList<>();
- annotators.add(new ConsoleAnnotator() {
+ annotators.add(new ConsoleAnnotator<>() {
@Override
public ConsoleAnnotator annotate(T context, MarkupText text) {
return a.annotate(context, text, charPos);
diff --git a/core/src/main/java/hudson/diagnosis/OldDataMonitor.java b/core/src/main/java/hudson/diagnosis/OldDataMonitor.java
index b29ec1a80fb2..ba589758cb28 100644
--- a/core/src/main/java/hudson/diagnosis/OldDataMonitor.java
+++ b/core/src/main/java/hudson/diagnosis/OldDataMonitor.java
@@ -149,7 +149,7 @@ public void onDeleted(Item item) {
};
@Extension
- public static final RunListener runDeleteListener = new RunListener() {
+ public static final RunListener runDeleteListener = new RunListener<>() {
@Override
public void onDeleted(Run run) {
remove(run, true);
diff --git a/core/src/main/java/hudson/init/impl/InitialUserContent.java b/core/src/main/java/hudson/init/impl/InitialUserContent.java
index 81cc279eb909..0e93164574a9 100644
--- a/core/src/main/java/hudson/init/impl/InitialUserContent.java
+++ b/core/src/main/java/hudson/init/impl/InitialUserContent.java
@@ -29,11 +29,11 @@
import hudson.Util;
import hudson.init.Initializer;
import hudson.model.Messages;
-import java.io.File;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
+import java.nio.file.Path;
import jenkins.model.Jenkins;
-import org.apache.commons.io.FileUtils;
/**
* Prepares userContent folder and put a readme if it doesn't exist.
@@ -42,10 +42,10 @@
public class InitialUserContent {
@Initializer(after = JOB_CONFIG_ADAPTED)
public static void init(Jenkins h) throws IOException {
- File userContentDir = new File(h.getRootDir(), "userContent");
- if (!Files.isDirectory(Util.fileToPath(userContentDir))) {
- Util.createDirectories(Util.fileToPath(userContentDir));
- FileUtils.writeStringToFile(new File(userContentDir, "readme.txt"), Messages.Hudson_USER_CONTENT_README() + "\n");
+ Path userContentDir = Util.fileToPath(h.getRootDir()).resolve("userContent");
+ if (!Files.isDirectory(userContentDir)) {
+ Util.createDirectories(userContentDir);
+ Files.writeString(userContentDir.resolve("readme.txt"), Messages.Hudson_USER_CONTENT_README() + System.lineSeparator(), StandardCharsets.UTF_8);
}
}
}
diff --git a/core/src/main/java/hudson/logging/LogRecorder.java b/core/src/main/java/hudson/logging/LogRecorder.java
index 4e49c019a10f..84ae1e1f1ec7 100644
--- a/core/src/main/java/hudson/logging/LogRecorder.java
+++ b/core/src/main/java/hudson/logging/LogRecorder.java
@@ -574,7 +574,7 @@ public List getLogRecords() {
* @since 1.519
*/
public Map> getSlaveLogRecords() {
- Map> result = new TreeMap<>(new Comparator() {
+ Map> result = new TreeMap<>(new Comparator<>() {
final Collator COLL = Collator.getInstance();
@Override
diff --git a/core/src/main/java/hudson/logging/LogRecorderManager.java b/core/src/main/java/hudson/logging/LogRecorderManager.java
index 7d3fab45dc64..70856024df12 100644
--- a/core/src/main/java/hudson/logging/LogRecorderManager.java
+++ b/core/src/main/java/hudson/logging/LogRecorderManager.java
@@ -78,6 +78,9 @@
* @author Kohsuke Kawaguchi
*/
public class LogRecorderManager extends AbstractModelObject implements ModelObjectWithChildren, StaplerProxy {
+
+ private static final Logger LOGGER = Logger.getLogger(LogRecorderManager.class.getName());
+
/**
* {@link LogRecorder}s keyed by their {@linkplain LogRecorder#getName()} name}.
*
@@ -104,7 +107,14 @@ public void setRecorders(List recorders) {
this.recorders = recorders;
Map values = recorders.stream()
- .collect(toMap(LogRecorder::getName, Function.identity()));
+ .collect(toMap(
+ LogRecorder::getName,
+ Function.identity(),
+ // see JENKINS-68752, ignore duplicates
+ (recorder1, recorder2) -> {
+ LOGGER.warning(String.format("Ignoring duplicate log recorder '%s', check $JENKINS_HOME/log and remove the duplicate recorder", recorder2.getName()));
+ return recorder1;
+ }));
((CopyOnWriteMap) logRecorders).replaceBy(values);
}
@@ -237,7 +247,7 @@ public void doRss(StaplerRequest req, StaplerResponse rsp) throws IOException, S
entryType = level;
}
- RSS.forwardToRss("Jenkins:log (" + entryType + " entries)", "", logs, new FeedAdapter() {
+ RSS.forwardToRss("Jenkins:log (" + entryType + " entries)", "", logs, new FeedAdapter<>() {
@Override
public String getEntryTitle(LogRecord entry) {
return entry.getMessage();
diff --git a/core/src/main/java/hudson/model/AbstractBuild.java b/core/src/main/java/hudson/model/AbstractBuild.java
index 0bd6947270f0..e19a8b17a505 100644
--- a/core/src/main/java/hudson/model/AbstractBuild.java
+++ b/core/src/main/java/hudson/model/AbstractBuild.java
@@ -158,7 +158,7 @@ public abstract class AbstractBuild, R extends A
*/
protected transient List buildEnvironments;
- private final transient LazyBuildMixIn.RunMixIn runMixIn = new LazyBuildMixIn.RunMixIn
() {
+ private final transient LazyBuildMixIn.RunMixIn
runMixIn = new LazyBuildMixIn.RunMixIn<>() {
@Override protected R asRun() {
return _this();
}
@@ -925,7 +925,7 @@ public boolean tearDown(AbstractBuild build, BuildListener listener) throws IOEx
@Override
@NonNull public List> getChangeSets() {
ChangeLogSet extends ChangeLogSet.Entry> cs = getChangeSet();
- return cs.isEmptySet() ? Collections.emptyList() : Collections.singletonList(cs);
+ return cs.isEmptySet() ? Collections.emptyList() : List.of(cs);
}
/**
@@ -995,7 +995,7 @@ public EnvironmentList getEnvironments() {
return new EnvironmentList(buildEnvironments);
}
- return new EnvironmentList(buildEnvironments == null ? Collections.emptyList() : Collections.unmodifiableList(new ArrayList<>(buildEnvironments)));
+ return new EnvironmentList(buildEnvironments == null ? Collections.emptyList() : List.copyOf(buildEnvironments));
}
public Calendar due() {
@@ -1194,11 +1194,11 @@ public RangeSet getDownstreamRelationship(AbstractProject that) {
public Iterable> getDownstreamBuilds(final AbstractProject, ?> that) {
final Iterable nums = getDownstreamRelationship(that).listNumbers();
- return new Iterable>() {
+ return new Iterable<>() {
@Override
public Iterator> iterator() {
return Iterators.removeNull(
- new AdaptedIterator>(nums) {
+ new AdaptedIterator<>(nums) {
@Override
protected AbstractBuild, ?> adapt(Integer item) {
return that.getBuildByNumber(item);
diff --git a/core/src/main/java/hudson/model/AbstractItem.java b/core/src/main/java/hudson/model/AbstractItem.java
index bc96c1b08dcf..50875f19b8fd 100644
--- a/core/src/main/java/hudson/model/AbstractItem.java
+++ b/core/src/main/java/hudson/model/AbstractItem.java
@@ -55,6 +55,8 @@
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -78,7 +80,6 @@
import jenkins.security.NotReallyRoleSensitiveCallable;
import jenkins.util.SystemProperties;
import jenkins.util.xml.XMLUtils;
-import org.apache.commons.io.FileUtils;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Copy;
import org.apache.tools.ant.types.FileSet;
@@ -110,6 +111,7 @@
// Item doesn't necessarily have to be Actionable, but
// Java doesn't let multiple inheritance.
@ExportedBean
+@SuppressFBWarnings(value = "THROWS_METHOD_THROWS_CLAUSE_THROWABLE", justification = "TODO needs triage")
public abstract class AbstractItem extends Actionable implements Item, HttpDeletable, AccessControlled, DescriptorByNameOwner, StaplerProxy {
private static final Logger LOGGER = Logger.getLogger(AbstractItem.class.getName());
@@ -850,7 +852,7 @@ public void writeConfigDotXml(OutputStream os) throws IOException {
IOUtils.copy(configFile.getFile(), os);
} else {
String encoding = configFile.sniffEncoding();
- String xml = FileUtils.readFileToString(configFile.getFile(), encoding);
+ String xml = Files.readString(Util.fileToPath(configFile.getFile()), Charset.forName(encoding));
Matcher matcher = SECRET_PATTERN.matcher(xml);
StringBuffer cleanXml = new StringBuffer();
while (matcher.find()) {
diff --git a/core/src/main/java/hudson/model/AbstractProject.java b/core/src/main/java/hudson/model/AbstractProject.java
index 7851de09833c..8b46d0cd0a7e 100644
--- a/core/src/main/java/hudson/model/AbstractProject.java
+++ b/core/src/main/java/hudson/model/AbstractProject.java
@@ -268,7 +268,7 @@ protected AbstractProject(ItemGroup parent, String name) {
}
private LazyBuildMixIn createBuildMixIn() {
- return new LazyBuildMixIn
() {
+ return new LazyBuildMixIn<>() {
@SuppressWarnings("unchecked") // untypable
@Override protected P asJob() {
return (P) AbstractProject.this;
@@ -1746,7 +1746,7 @@ protected void submit(StaplerRequest req, StaplerResponse rsp) throws IOExceptio
super.submit(req, rsp);
JSONObject json = req.getSubmittedForm();
- makeDisabled(json.optBoolean("disable"));
+ makeDisabled(!json.optBoolean("enable"));
jdk = json.optString("jdk", null);
diff --git a/core/src/main/java/hudson/model/Actionable.java b/core/src/main/java/hudson/model/Actionable.java
index 6fcb173fc6ad..053fb0c8cfe0 100644
--- a/core/src/main/java/hudson/model/Actionable.java
+++ b/core/src/main/java/hudson/model/Actionable.java
@@ -31,6 +31,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -227,7 +228,7 @@ public boolean removeAction(@Nullable Action a) {
return false;
}
// CopyOnWriteArrayList does not support Iterator.remove, so need to do it this way:
- return getActions().removeAll(Collections.singleton(a));
+ return getActions().removeAll(Set.of(a));
}
/**
diff --git a/core/src/main/java/hudson/model/ComputerSet.java b/core/src/main/java/hudson/model/ComputerSet.java
index ecef09a90fc3..211c795ee95c 100644
--- a/core/src/main/java/hudson/model/ComputerSet.java
+++ b/core/src/main/java/hudson/model/ComputerSet.java
@@ -146,7 +146,7 @@ public static Map, NodeMonitor> getNonIgnoredMonitors()
* Gets all the agent names.
*/
public List get_slaveNames() {
- return new AbstractList() {
+ return new AbstractList<>() {
final List nodes = Jenkins.get().getNodes();
@Override
diff --git a/core/src/main/java/hudson/model/DependencyGraph.java b/core/src/main/java/hudson/model/DependencyGraph.java
index 3788e2aefddc..aa9810792a55 100644
--- a/core/src/main/java/hudson/model/DependencyGraph.java
+++ b/core/src/main/java/hudson/model/DependencyGraph.java
@@ -100,10 +100,10 @@ public void build() {
/**
*
*
- * See https://en.wikipedia.org/wiki/Tarjan's_strongly_connected_components_algorithm
+ * See Tarjan's strongly connected components algorithm
*/
private void topologicalDagSort() {
- DirectedGraph g = new DirectedGraph() {
+ DirectedGraph g = new DirectedGraph<>() {
@Override
protected Collection nodes() {
final Set nodes = new HashSet<>();
@@ -342,7 +342,7 @@ private Map> finalize(Map NAME_COMPARATOR = new Comparator() {
+ private static final Comparator NAME_COMPARATOR = new Comparator<>() {
@Override
public int compare(DependencyGroup lhs, DependencyGroup rhs) {
int cmp = lhs.getUpstreamProject().getName().compareTo(rhs.getUpstreamProject().getName());
diff --git a/core/src/main/java/hudson/model/Descriptor.java b/core/src/main/java/hudson/model/Descriptor.java
index bf0b0d5ccd0c..716b73031510 100644
--- a/core/src/main/java/hudson/model/Descriptor.java
+++ b/core/src/main/java/hudson/model/Descriptor.java
@@ -59,13 +59,13 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -568,7 +568,7 @@ public T newInstance(StaplerRequest req) throws FormException {
* Always non-null (see note above.) This object includes represents the entire submission.
* @param formData
* The JSON object that captures the configuration data for this {@link Descriptor}.
- * See https://www.jenkins.io/doc/developer/forms/structured-form-submission/
+ * See the developer documentation.
* Always non-null.
*
* @throws FormException
@@ -599,7 +599,7 @@ public T newInstance(@Nullable StaplerRequest req, @NonNull JSONObject formData)
* Replacement for {@link StaplerRequest#bindJSON(Class, JSONObject)} which honors {@link #newInstance(StaplerRequest, JSONObject)}.
* This is automatically used inside {@link #newInstance(StaplerRequest, JSONObject)} so a direct call would only be necessary
* in case the top level binding might use a {@link Descriptor} which overrides {@link #newInstance(StaplerRequest, JSONObject)}.
- * @since TODO
+ * @since 2.342
*/
public static T bindJSON(StaplerRequest req, Class type, JSONObject src) {
return bindJSON(req, type, src, false);
@@ -820,7 +820,7 @@ public boolean configure(StaplerRequest req) throws FormException {
*
* @param json
* The JSON object that captures the configuration data for this {@link Descriptor}.
- * See https://www.jenkins.io/doc/developer/forms/structured-form-submission/
+ * See the developer documentation.
* @return false
* to keep the client in the same config page.
*/
@@ -863,7 +863,7 @@ Permission getRequiredGlobalConfigPagePermission() {
}
private String getViewPage(Class> clazz, String pageName, String defaultValue) {
- return getViewPage(clazz, Collections.singleton(pageName), defaultValue);
+ return getViewPage(clazz, Set.of(pageName), defaultValue);
}
private String getViewPage(Class> clazz, Collection pageNames, String defaultValue) {
@@ -978,7 +978,7 @@ public void doHelp(StaplerRequest req, StaplerResponse rsp) throws IOException,
rsp.setContentType("text/html;charset=UTF-8");
try (InputStream in = url.openStream()) {
String literal = IOUtils.toString(in, StandardCharsets.UTF_8);
- rsp.getWriter().println(Util.replaceMacro(literal, Collections.singletonMap("rootURL", req.getContextPath())));
+ rsp.getWriter().println(Util.replaceMacro(literal, Map.of("rootURL", req.getContextPath())));
}
return;
}
diff --git a/core/src/main/java/hudson/model/DirectoryBrowserSupport.java b/core/src/main/java/hudson/model/DirectoryBrowserSupport.java
index 1df1e1ab69a8..ba62d01eb6c9 100644
--- a/core/src/main/java/hudson/model/DirectoryBrowserSupport.java
+++ b/core/src/main/java/hudson/model/DirectoryBrowserSupport.java
@@ -39,7 +39,6 @@
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
-import java.util.Collections;
import java.util.Comparator;
import java.util.GregorianCalendar;
import java.util.LinkedHashMap;
@@ -507,10 +506,7 @@ private List buildParentPath(String pathList, int restSize) {
private static String createBackRef(int times) {
if (times == 0) return "./";
- StringBuilder buf = new StringBuilder(3 * times);
- for (int i = 0; i < times; i++)
- buf.append("../");
- return buf.toString();
+ return "../".repeat(times);
}
private static void zip(StaplerResponse rsp, VirtualFile root, VirtualFile dir, String glob) throws IOException, InterruptedException {
@@ -764,7 +760,7 @@ private static List> buildChildPaths(VirtualFile cur, Locale locale)
for (VirtualFile f : files) {
Path p = new Path(Util.rawEncode(f.getName()), f.getName(), f.isDirectory(), f.length(), f.canRead(), f.lastModified());
if (!f.isDirectory()) {
- r.add(Collections.singletonList(p));
+ r.add(List.of(p));
} else {
// find all empty intermediate directory
List l = new ArrayList<>();
diff --git a/core/src/main/java/hudson/model/DownloadService.java b/core/src/main/java/hudson/model/DownloadService.java
index 000ef9f48d2f..b9a5610c4e35 100644
--- a/core/src/main/java/hudson/model/DownloadService.java
+++ b/core/src/main/java/hudson/model/DownloadService.java
@@ -388,7 +388,7 @@ public FormValidation updateNow() throws IOException {
}
String jsonString;
try {
- jsonString = loadJSONHTML(new URL(site + ".html?id=" + URLEncoder.encode(getId(), "UTF-8") + "&version=" + URLEncoder.encode(Jenkins.VERSION, "UTF-8")));
+ jsonString = loadJSONHTML(new URL(site + ".html?id=" + URLEncoder.encode(getId(), StandardCharsets.UTF_8) + "&version=" + URLEncoder.encode(Jenkins.VERSION, StandardCharsets.UTF_8)));
toolInstallerMetadataExists = true;
} catch (Exception e) {
LOGGER.log(Level.FINE, "Could not load json from " + site, e);
diff --git a/core/src/main/java/hudson/model/Executor.java b/core/src/main/java/hudson/model/Executor.java
index e7b14b72aebf..1214a277d8f7 100644
--- a/core/src/main/java/hudson/model/Executor.java
+++ b/core/src/main/java/hudson/model/Executor.java
@@ -32,6 +32,7 @@
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.FilePath;
import hudson.Functions;
import hudson.Util;
@@ -89,6 +90,12 @@
* @author Kohsuke Kawaguchi
*/
@ExportedBean
+@SuppressFBWarnings(
+ value = {
+ "THROWS_METHOD_THROWS_CLAUSE_BASIC_EXCEPTION",
+ "THROWS_METHOD_THROWS_CLAUSE_THROWABLE"
+ },
+ justification = "TODO needs triage")
public class Executor extends Thread implements ModelObject {
protected final @NonNull Computer owner;
private final Queue queue;
@@ -349,7 +356,7 @@ public void run() {
SubTask task;
// transition from idle to building.
// perform this state change as an atomic operation wrt other queue operations
- task = Queue.withLock(new Callable() {
+ task = Queue.withLock(new Callable<>() {
@Override
public SubTask call() throws Exception {
if (!owner.isOnline()) {
diff --git a/core/src/main/java/hudson/model/Fingerprint.java b/core/src/main/java/hudson/model/Fingerprint.java
index d4b57badaefc..d49257967101 100644
--- a/core/src/main/java/hudson/model/Fingerprint.java
+++ b/core/src/main/java/hudson/model/Fingerprint.java
@@ -362,10 +362,10 @@ private RangeSet(Range initial) {
*/
public Iterable listNumbers() {
final List ranges = getRanges();
- return new Iterable() {
+ return new Iterable<>() {
@Override
public Iterator iterator() {
- return new Iterators.FlattenIterator(ranges) {
+ return new Iterators.FlattenIterator<>(ranges) {
@Override
protected Iterator expand(Range range) {
return Iterators.sequence(range.start, range.end).iterator();
@@ -380,10 +380,10 @@ protected Iterator expand(Range range) {
*/
public Iterable listNumbersReverse() {
final List ranges = getRanges();
- return new Iterable() {
+ return new Iterable<>() {
@Override
public Iterator iterator() {
- return new Iterators.FlattenIterator(Iterators.reverse(ranges)) {
+ return new Iterators.FlattenIterator<>(Iterators.reverse(ranges)) {
@Override
protected Iterator expand(Range range) {
return Iterators.reverseSequence(range.start, range.end).iterator();
@@ -1164,7 +1164,7 @@ public synchronized boolean trim() throws IOException {
this.transientFacets = Collections.unmodifiableList(transientFacets);
}
- return new AbstractCollection() {
+ return new AbstractCollection<>() {
@Override
public Iterator iterator() {
return Iterators.sequence(facets.iterator(), transientFacets.iterator());
@@ -1208,7 +1208,7 @@ public int size() {
*/
public @NonNull Collection getSortedFacets() {
List r = new ArrayList<>(getFacets());
- r.sort(new Comparator() {
+ r.sort(new Comparator<>() {
@Override
public int compare(FingerprintFacet o1, FingerprintFacet o2) {
long a = o1.getTimestamp();
diff --git a/core/src/main/java/hudson/model/ItemGroupMixIn.java b/core/src/main/java/hudson/model/ItemGroupMixIn.java
index 748a13cc6ec4..e9a526ebbe6c 100644
--- a/core/src/main/java/hudson/model/ItemGroupMixIn.java
+++ b/core/src/main/java/hudson/model/ItemGroupMixIn.java
@@ -24,6 +24,7 @@
package hudson.model;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.Util;
import hudson.XmlFile;
import hudson.model.listeners.ItemListener;
@@ -61,6 +62,7 @@
* @author Kohsuke Kawaguchi
* @see ViewGroupMixIn
*/
+@SuppressFBWarnings(value = "THROWS_METHOD_THROWS_CLAUSE_THROWABLE", justification = "TODO needs triage")
public abstract class ItemGroupMixIn {
/**
* {@link ItemGroup} for which we are working.
diff --git a/core/src/main/java/hudson/model/JDK.java b/core/src/main/java/hudson/model/JDK.java
index ae642aba3305..50de1401f029 100644
--- a/core/src/main/java/hudson/model/JDK.java
+++ b/core/src/main/java/hudson/model/JDK.java
@@ -197,7 +197,7 @@ public List extends ToolInstaller> getDefaultInstallers() {
Class extends ToolInstaller> jdkInstallerClass = Jenkins.get().getPluginManager()
.uberClassLoader.loadClass("hudson.tools.JDKInstaller").asSubclass(ToolInstaller.class);
Constructor extends ToolInstaller> constructor = jdkInstallerClass.getConstructor(String.class, boolean.class);
- return Collections.singletonList(constructor.newInstance(null, false));
+ return List.of(constructor.newInstance(null, false));
} catch (ClassNotFoundException e) {
return Collections.emptyList();
} catch (Exception e) {
diff --git a/core/src/main/java/hudson/model/Job.java b/core/src/main/java/hudson/model/Job.java
index 9b492f4f6cfa..d7444c2304b0 100644
--- a/core/src/main/java/hudson/model/Job.java
+++ b/core/src/main/java/hudson/model/Job.java
@@ -81,6 +81,7 @@
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.SortedMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -505,7 +506,7 @@ public void suggest(String token, List result) {
@Override
public Collection extends Job> getAllJobs() {
- return Collections.singleton(this);
+ return Set.of(this);
}
/**
@@ -623,7 +624,7 @@ protected HistoryWidget createHistoryWidget() {
return new HistoryWidget(this, getBuilds(), HISTORY_ADAPTER);
}
- public static final HistoryWidget.Adapter HISTORY_ADAPTER = new Adapter() {
+ public static final HistoryWidget.Adapter HISTORY_ADAPTER = new Adapter<>() {
@Override
public int compare(Run record, String key) {
try {
@@ -1120,7 +1121,7 @@ class FeedItem {
RSS.forwardToRss(
getDisplayName() + scmDisplayName + " changes",
getUrl() + "changes",
- entries, new FeedAdapter() {
+ entries, new FeedAdapter<>() {
@Override
public String getEntryTitle(FeedItem item) {
return "#" + item.getBuild().number + ' ' + item.e.getMsg() + " (" + item.e.getAuthor() + ")";
diff --git a/core/src/main/java/hudson/model/JobProperty.java b/core/src/main/java/hudson/model/JobProperty.java
index fe02891987e9..14ff87591fe9 100644
--- a/core/src/main/java/hudson/model/JobProperty.java
+++ b/core/src/main/java/hudson/model/JobProperty.java
@@ -36,6 +36,7 @@
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
import jenkins.model.Jenkins;
import jenkins.model.OptionalJobProperty;
import net.sf.json.JSONObject;
@@ -134,7 +135,7 @@ public Collection extends Action> getJobActions(J job) {
// delegate to getJobAction (singular) for backward compatible behavior
Action a = getJobAction(job);
if (a == null) return Collections.emptyList();
- return Collections.singletonList(a);
+ return List.of(a);
}
//
diff --git a/core/src/main/java/hudson/model/Label.java b/core/src/main/java/hudson/model/Label.java
index 12426e8ba9e6..c285a1a28fda 100644
--- a/core/src/main/java/hudson/model/Label.java
+++ b/core/src/main/java/hudson/model/Label.java
@@ -185,7 +185,7 @@ public String getSearchUrl() {
* {@link LabelAtom}s.
*/
public final boolean matches(final Collection labels) {
- return matches(new VariableResolver() {
+ return matches(new VariableResolver<>() {
@Override
public Boolean resolve(String name) {
for (LabelAtom a : labels)
@@ -619,7 +619,7 @@ public static Label parseExpression(@NonNull String labelExpression) throws ANTL
/**
* Collects all the atoms in the expression.
*/
- private static final LabelVisitor> ATOM_COLLECTOR = new LabelVisitor>() {
+ private static final LabelVisitor> ATOM_COLLECTOR = new LabelVisitor<>() {
@Override
public Void onAtom(LabelAtom a, Set param) {
param.add(a);
diff --git a/core/src/main/java/hudson/model/ListView.java b/core/src/main/java/hudson/model/ListView.java
index 9f47962b92bd..3476b81cc035 100644
--- a/core/src/main/java/hudson/model/ListView.java
+++ b/core/src/main/java/hudson/model/ListView.java
@@ -143,7 +143,7 @@ protected Object readResolve() {
includePattern = Pattern.compile(includeRegex);
} catch (PatternSyntaxException x) {
includeRegex = null;
- OldDataMonitor.report(this, Collections.singleton(x));
+ OldDataMonitor.report(this, Set.of(x));
}
}
synchronized (this) {
diff --git a/core/src/main/java/hudson/model/ParametersDefinitionProperty.java b/core/src/main/java/hudson/model/ParametersDefinitionProperty.java
index 26b59fdf95f6..d3eb4fec929a 100644
--- a/core/src/main/java/hudson/model/ParametersDefinitionProperty.java
+++ b/core/src/main/java/hudson/model/ParametersDefinitionProperty.java
@@ -39,8 +39,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import jenkins.model.Jenkins;
@@ -112,7 +112,7 @@ public List getParameterDefinitionNames() {
@NonNull
@Override
public Collection getJobActions(Job, ?> job) {
- return Collections.singleton(this);
+ return Set.of(this);
}
@Deprecated
diff --git a/core/src/main/java/hudson/model/Queue.java b/core/src/main/java/hudson/model/Queue.java
index 50ad97232bd5..93765f2be4ab 100644
--- a/core/src/main/java/hudson/model/Queue.java
+++ b/core/src/main/java/hudson/model/Queue.java
@@ -171,6 +171,7 @@
* @see QueueTaskDispatcher
*/
@ExportedBean
+@SuppressFBWarnings(value = "THROWS_METHOD_THROWS_CLAUSE_BASIC_EXCEPTION", justification = "TODO needs triage")
public class Queue extends ResourceController implements Saveable {
/**
@@ -324,7 +325,7 @@ public String toString() {
private transient volatile QueueSorter sorter;
- private final transient AtmostOneTaskExecutor maintainerThread = new AtmostOneTaskExecutor<>(new Callable() {
+ private final transient AtmostOneTaskExecutor maintainerThread = new AtmostOneTaskExecutor<>(new Callable<>() {
@Override
public Void call() throws Exception {
maintain();
@@ -1986,7 +1987,7 @@ default boolean isConcurrentBuild() {
* @since 1.377
*/
default Collection extends SubTask> getSubTasks() {
- return Collections.singleton(this);
+ return Set.of(this);
}
/**
diff --git a/core/src/main/java/hudson/model/ResourceController.java b/core/src/main/java/hudson/model/ResourceController.java
index a3702ab79e61..2eabd0616b3c 100644
--- a/core/src/main/java/hudson/model/ResourceController.java
+++ b/core/src/main/java/hudson/model/ResourceController.java
@@ -39,6 +39,12 @@
* Controls mutual exclusion of {@link ResourceList}.
* @author Kohsuke Kawaguchi
*/
+@SuppressFBWarnings(
+ value = {
+ "THROWS_METHOD_THROWS_CLAUSE_BASIC_EXCEPTION",
+ "THROWS_METHOD_THROWS_CLAUSE_THROWABLE"
+ },
+ justification = "TODO needs triage")
public class ResourceController {
/**
* {@link ResourceList}s that are used by activities that are in progress.
@@ -48,10 +54,10 @@ public class ResourceController {
/**
* View of {@link #inProgress} that exposes its {@link ResourceList}.
*/
- private final Collection resourceView = new AbstractCollection() {
+ private final Collection resourceView = new AbstractCollection<>() {
@Override
public Iterator iterator() {
- return new AdaptedIterator(inProgress.iterator()) {
+ return new AdaptedIterator<>(inProgress.iterator()) {
@Override
protected ResourceList adapt(ResourceActivity item) {
return item.getResourceList();
@@ -123,7 +129,7 @@ public void run() {
*/
public boolean canRun(final ResourceList resources) {
try {
- return _withLock(new Callable() {
+ return _withLock(new Callable<>() {
@Override
public Boolean call() {
return !inUse.isCollidingWith(resources);
@@ -144,7 +150,7 @@ public Boolean call() {
*/
public Resource getMissingResource(final ResourceList resources) {
try {
- return _withLock(new Callable() {
+ return _withLock(new Callable<>() {
@Override
public Resource call() {
return resources.getConflict(inUse);
diff --git a/core/src/main/java/hudson/model/Run.java b/core/src/main/java/hudson/model/Run.java
index 83f11cdef4a0..094a02bd2fa3 100644
--- a/core/src/main/java/hudson/model/Run.java
+++ b/core/src/main/java/hudson/model/Run.java
@@ -319,6 +319,7 @@ private enum State {
/**
* Creates a new {@link Run}.
* @param job Owner job
+ * @see LazyBuildMixIn#newBuild
*/
protected Run(@NonNull JobT job) throws IOException {
this(job, System.currentTimeMillis());
@@ -347,6 +348,7 @@ protected Run(@NonNull JobT job, long timestamp) {
/**
* Loads a run from a log file.
+ * @see LazyBuildMixIn#loadBuild
*/
protected Run(@NonNull JobT project, @NonNull File buildDir) throws IOException {
this.project = project;
@@ -2541,7 +2543,7 @@ protected void submit(JSONObject json) throws IOException {
/**
* Sort by date. Newer ones first.
*/
- public static final Comparator ORDER_BY_DATE = new Comparator() {
+ public static final Comparator ORDER_BY_DATE = new Comparator<>() {
@Override
public int compare(@NonNull Run lhs, @NonNull Run rhs) {
long lt = lhs.getTimeInMillis();
diff --git a/core/src/main/java/hudson/model/RunMap.java b/core/src/main/java/hudson/model/RunMap.java
index 955037ab3555..ca16fee660d2 100644
--- a/core/src/main/java/hudson/model/RunMap.java
+++ b/core/src/main/java/hudson/model/RunMap.java
@@ -101,7 +101,7 @@ public boolean remove(R run) {
*/
@Override
public Iterator iterator() {
- return new Iterator() {
+ return new Iterator<>() {
R last = null;
R next = newestBuild();
diff --git a/core/src/main/java/hudson/model/Slave.java b/core/src/main/java/hudson/model/Slave.java
index 1833acf9501a..cf6e6b437862 100644
--- a/core/src/main/java/hudson/model/Slave.java
+++ b/core/src/main/java/hudson/model/Slave.java
@@ -59,10 +59,7 @@
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.JarFile;
@@ -744,5 +741,5 @@ private Object readResolve() {
/**
* Provides a collection of file names, which are accessible via /jnlpJars link.
*/
- private static final Set ALLOWED_JNLPJARS_FILES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("agent.jar", "slave.jar", "remoting.jar", "jenkins-cli.jar", "hudson-cli.jar")));
+ private static final Set ALLOWED_JNLPJARS_FILES = Set.of("agent.jar", "slave.jar", "remoting.jar", "jenkins-cli.jar", "hudson-cli.jar");
}
diff --git a/core/src/main/java/hudson/model/UpdateCenter.java b/core/src/main/java/hudson/model/UpdateCenter.java
index 1ac875c03cdf..3aad76f1f043 100644
--- a/core/src/main/java/hudson/model/UpdateCenter.java
+++ b/core/src/main/java/hudson/model/UpdateCenter.java
@@ -114,7 +114,6 @@
import net.sf.json.JSONObject;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.CountingInputStream;
-import org.apache.commons.io.output.NullOutputStream;
import org.jenkinsci.Symbol;
import org.jvnet.localizer.Localizable;
import org.kohsuke.accmod.Restricted;
@@ -1422,8 +1421,8 @@ private void testConnection(URL url) throws IOException {
throw new HttpRetryException("Invalid response code (" + responseCode + ") from URL: " + url, responseCode);
}
} else {
- try (InputStream is = connection.getInputStream()) {
- IOUtils.copy(is, NullOutputStream.NULL_OUTPUT_STREAM);
+ try (InputStream is = connection.getInputStream(); OutputStream os = OutputStream.nullOutputStream()) {
+ IOUtils.copy(is, os);
}
}
} catch (SSLHandshakeException e) {
diff --git a/core/src/main/java/hudson/model/UpdateSite.java b/core/src/main/java/hudson/model/UpdateSite.java
index 389e3cb3890f..b18bf038d8d4 100644
--- a/core/src/main/java/hudson/model/UpdateSite.java
+++ b/core/src/main/java/hudson/model/UpdateSite.java
@@ -49,6 +49,7 @@
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
@@ -104,6 +105,7 @@
* @since 1.333
*/
@ExportedBean
+@SuppressFBWarnings(value = "THROWS_METHOD_THROWS_CLAUSE_BASIC_EXCEPTION", justification = "TODO needs triage")
public class UpdateSite {
/**
* What's the time stamp of data file?
@@ -214,7 +216,7 @@ public long getDataTimestamp() {
@Restricted(NoExternalUse.class)
public @NonNull FormValidation updateDirectlyNow(boolean signatureCheck) throws IOException {
- return updateData(DownloadService.loadJSON(new URL(getUrl() + "?id=" + URLEncoder.encode(getId(), "UTF-8") + "&version=" + URLEncoder.encode(Jenkins.VERSION, "UTF-8"))), signatureCheck);
+ return updateData(DownloadService.loadJSON(new URL(getUrl() + "?id=" + URLEncoder.encode(getId(), StandardCharsets.UTF_8) + "&version=" + URLEncoder.encode(Jenkins.VERSION, StandardCharsets.UTF_8))), signatureCheck);
}
private FormValidation updateData(String json, boolean signatureCheck)
@@ -529,7 +531,7 @@ public String getDownloadUrl() {
* Is this the legacy default update center site?
* @deprecated
* Will be removed, currently returns always false.
- * @since TODO
+ * @since 2.343
*/
@Deprecated
@Restricted(NoExternalUse.class)
@@ -1023,11 +1025,7 @@ public boolean isRelevant() {
switch (this.type) {
case CORE:
VersionNumber current = Jenkins.getVersion();
-
- if (!isRelevantToVersion(current)) {
- return false;
- }
- return true;
+ return isRelevantToVersion(current);
case PLUGIN:
// check whether plugin is installed
diff --git a/core/src/main/java/hudson/model/User.java b/core/src/main/java/hudson/model/User.java
index bc2a86138d1a..8f9ca606dca9 100644
--- a/core/src/main/java/hudson/model/User.java
+++ b/core/src/main/java/hudson/model/User.java
@@ -441,7 +441,7 @@ private LegitimateButUnknownUserDetails(String username) throws IllegalArgumentE
super(
username, "",
true, true, true, true,
- Collections.singleton(SecurityRealm.AUTHENTICATED_AUTHORITY2)
+ Set.of(SecurityRealm.AUTHENTICATED_AUTHORITY2)
);
}
}
diff --git a/core/src/main/java/hudson/model/View.java b/core/src/main/java/hudson/model/View.java
index 856ea45f3bea..6374dd3e3f49 100644
--- a/core/src/main/java/hudson/model/View.java
+++ b/core/src/main/java/hudson/model/View.java
@@ -516,9 +516,7 @@ private boolean filterQueueItemTest(Queue.Item item, Collection vi
// Check root project for sub-job projects (e.g. matrix jobs).
if (item.task instanceof AbstractProject, ?>) {
AbstractProject, ?> project = (AbstractProject, ?>) item.task;
- if (viewItems.contains(project.getRootProject())) {
- return true;
- }
+ return viewItems.contains(project.getRootProject());
}
return false;
}
@@ -1265,7 +1263,7 @@ public void updateByXml(Source source) throws IOException {
public ModelObjectWithContextMenu.ContextMenu doChildrenContextMenu(StaplerRequest request, StaplerResponse response) throws Exception {
ModelObjectWithContextMenu.ContextMenu m = new ModelObjectWithContextMenu.ContextMenu();
for (TopLevelItem i : getItems())
- m.add(i.getShortUrl(), i.getDisplayName());
+ m.add(Functions.getRelativeLinkTo(i), Functions.getRelativeDisplayNameFrom(i, getOwner().getItemGroup()));
return m;
}
diff --git a/core/src/main/java/hudson/model/labels/LabelAtom.java b/core/src/main/java/hudson/model/labels/LabelAtom.java
index 52779eb6fce1..84ee083c488d 100644
--- a/core/src/main/java/hudson/model/labels/LabelAtom.java
+++ b/core/src/main/java/hudson/model/labels/LabelAtom.java
@@ -170,7 +170,7 @@ public V accept(LabelVisitor visitor, P param) {
@Override
public Set listAtoms() {
- return Collections.singleton(this);
+ return Set.of(this);
}
@Override
diff --git a/core/src/main/java/hudson/node_monitors/ResponseTimeMonitor.java b/core/src/main/java/hudson/node_monitors/ResponseTimeMonitor.java
index 0a4be196009e..1ffdcc1a54ee 100644
--- a/core/src/main/java/hudson/node_monitors/ResponseTimeMonitor.java
+++ b/core/src/main/java/hudson/node_monitors/ResponseTimeMonitor.java
@@ -45,7 +45,7 @@
*/
public class ResponseTimeMonitor extends NodeMonitor {
@Extension
- public static final AbstractNodeMonitorDescriptor DESCRIPTOR = new AbstractAsyncNodeMonitorDescriptor() {
+ public static final AbstractNodeMonitorDescriptor DESCRIPTOR = new AbstractAsyncNodeMonitorDescriptor<>() {
@Override
protected Callable createCallable(Computer c) {
diff --git a/core/src/main/java/hudson/os/SU.java b/core/src/main/java/hudson/os/SU.java
index 185110d83781..d98520ab5ae1 100644
--- a/core/src/main/java/hudson/os/SU.java
+++ b/core/src/main/java/hudson/os/SU.java
@@ -93,7 +93,7 @@ protected Process sudoWithPass(ArgumentListBuilder args) throws IOException {
Process p = pb.start();
// TODO: use -p to detect prompt
// TODO: detect if the password didn't work
- try (PrintStream ps = new PrintStream(p.getOutputStream(), false, Charset.defaultCharset().name())) {
+ try (PrintStream ps = new PrintStream(p.getOutputStream(), false, Charset.defaultCharset())) {
ps.println(rootPassword);
ps.println(rootPassword);
ps.println(rootPassword);
diff --git a/core/src/main/java/hudson/os/WindowsUtil.java b/core/src/main/java/hudson/os/WindowsUtil.java
index 7ec4637e59e1..1299024285ea 100644
--- a/core/src/main/java/hudson/os/WindowsUtil.java
+++ b/core/src/main/java/hudson/os/WindowsUtil.java
@@ -36,7 +36,7 @@
/**
* Utilities for the Windows Platform.
* Adapted from:
- * https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/
+ * Everyone quotes command line arguments the wrong way
*
* @since 2.183
*/
@@ -70,9 +70,7 @@ public class WindowsUtil {
}
// else backslashes have no special meaning and don't need to be escaped here
- for (int j = 0; j < nrBackslashes; j++) {
- sb.append('\\');
- }
+ sb.append("\\".repeat(Math.max(0, nrBackslashes)));
if (i < end) {
sb.append(argument.charAt(i));
diff --git a/core/src/main/java/hudson/scm/EditType.java b/core/src/main/java/hudson/scm/EditType.java
index 7672b09db2e4..62967b114205 100644
--- a/core/src/main/java/hudson/scm/EditType.java
+++ b/core/src/main/java/hudson/scm/EditType.java
@@ -24,8 +24,6 @@
package hudson.scm;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import org.kohsuke.stapler.export.CustomExportedBean;
@@ -60,5 +58,5 @@ public String toExportedObject() {
public static final EditType EDIT = new EditType("edit", "The file was modified");
public static final EditType DELETE = new EditType("delete", "The file was removed");
- public static final List ALL = Collections.unmodifiableList(Arrays.asList(ADD, EDIT, DELETE));
+ public static final List ALL = List.of(ADD, EDIT, DELETE);
}
diff --git a/core/src/main/java/hudson/scm/EmptyChangeLogSet.java b/core/src/main/java/hudson/scm/EmptyChangeLogSet.java
index 2f5ffdcbff8b..bae8ebd882f0 100644
--- a/core/src/main/java/hudson/scm/EmptyChangeLogSet.java
+++ b/core/src/main/java/hudson/scm/EmptyChangeLogSet.java
@@ -13,7 +13,7 @@
*/
final class EmptyChangeLogSet extends ChangeLogSet {
/*package*/ EmptyChangeLogSet(Run, ?> build) {
- super(build, new RepositoryBrowser() {
+ super(build, new RepositoryBrowser<>() {
@Override public URL getChangeSetLink(ChangeLogSet.Entry changeSet) throws IOException {
return null;
}
diff --git a/core/src/main/java/hudson/search/Search.java b/core/src/main/java/hudson/search/Search.java
index 9c9aac5e72d6..70458355323d 100644
--- a/core/src/main/java/hudson/search/Search.java
+++ b/core/src/main/java/hudson/search/Search.java
@@ -339,7 +339,7 @@ static final class TokenList {
* (both end inclusive.)
*/
public List subSequence(final int start) {
- return new AbstractList() {
+ return new AbstractList<>() {
@Override
public String get(int index) {
StringBuilder buf = new StringBuilder();
diff --git a/core/src/main/java/hudson/security/BasicAuthenticationFilter.java b/core/src/main/java/hudson/security/BasicAuthenticationFilter.java
index dd29dc3004fe..b2a06024278b 100644
--- a/core/src/main/java/hudson/security/BasicAuthenticationFilter.java
+++ b/core/src/main/java/hudson/security/BasicAuthenticationFilter.java
@@ -29,6 +29,7 @@
import hudson.util.Scrambler;
import java.io.IOException;
import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
@@ -168,7 +169,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
// ... but first let the container authenticate this request
RequestDispatcher d = servletContext.getRequestDispatcher("/j_security_check?j_username=" +
- URLEncoder.encode(username, "UTF-8") + "&j_password=" + URLEncoder.encode(password, "UTF-8"));
+ URLEncoder.encode(username, StandardCharsets.UTF_8) + "&j_password=" + URLEncoder.encode(password, StandardCharsets.UTF_8));
d.include(req, rsp);
}
diff --git a/core/src/main/java/hudson/security/HudsonAuthenticationEntryPoint.java b/core/src/main/java/hudson/security/HudsonAuthenticationEntryPoint.java
index c81c642650ff..d87b38cbc0ea 100644
--- a/core/src/main/java/hudson/security/HudsonAuthenticationEntryPoint.java
+++ b/core/src/main/java/hudson/security/HudsonAuthenticationEntryPoint.java
@@ -82,7 +82,7 @@ public void commence(HttpServletRequest req, HttpServletResponse rsp, Authentica
String uriFrom = req.getRequestURI();
if (req.getQueryString() != null && !req.getQueryString().isEmpty()) uriFrom += "?" + req.getQueryString();
String loginForm = req.getContextPath() + loginFormUrl;
- loginForm = MessageFormat.format(loginForm, URLEncoder.encode(uriFrom, "UTF-8"));
+ loginForm = MessageFormat.format(loginForm, URLEncoder.encode(uriFrom, StandardCharsets.UTF_8));
req.setAttribute("loginForm", loginForm);
rsp.setStatus(SC_FORBIDDEN);
diff --git a/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java b/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java
index 91376af16efd..d25b01c02035 100644
--- a/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java
+++ b/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java
@@ -55,6 +55,8 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.Random;
+import java.util.Set;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -205,7 +207,14 @@ public Details load(String username) throws UsernameNotFoundException {
@Override
protected UserDetails authenticate2(String username, String password) throws AuthenticationException {
- Details u = load(username);
+ Details u;
+ try {
+ u = load(username);
+ } catch (UsernameNotFoundException ex) {
+ // Waste time to prevent timing attacks distinguishing existing and non-existing user
+ PASSWORD_ENCODER.matches(password, ENCODED_INVALID_USER_PASSWORD);
+ throw ex;
+ }
if (!u.isPasswordCorrect(password)) {
throw new BadCredentialsException("Bad credentials");
}
@@ -578,7 +587,7 @@ public User getUser(String id) {
}
// TODO
- private static final Collection extends GrantedAuthority> TEST_AUTHORITY = Collections.singleton(AUTHENTICATED_AUTHORITY2);
+ private static final Collection extends GrantedAuthority> TEST_AUTHORITY = Set.of(AUTHENTICATED_AUTHORITY2);
public static final class SignupInfo {
public String username, password1, password2, fullname, email, captcha;
@@ -899,7 +908,7 @@ public boolean matches(CharSequence rawPassword, String encodedPassword) {
/**
* Returns true if the supplied hash looks like a bcrypt encoded hash value, based off of the
- * implementation defined in jBCrypt and: https://en.wikipedia.org/wiki/Bcrypt.
+ * implementation defined in jBCrypt and the Wikipedia page.
*
*/
public boolean isHashValid(String hash) {
@@ -963,6 +972,19 @@ public boolean isPasswordHashed(String password) {
public static final MultiPasswordEncoder PASSWORD_ENCODER = new MultiPasswordEncoder();
+ /**
+ * This value is used to prevent timing discrepancies when trying to authenticate with an invalid username
+ * compared to just a wrong password. If the user doesn't exist, compare the provided password with this value.
+ */
+ private static final String ENCODED_INVALID_USER_PASSWORD = PASSWORD_ENCODER.encode(generatePassword());
+
+ @SuppressFBWarnings(value = {"DMI_RANDOM_USED_ONLY_ONCE", "PREDICTABLE_RANDOM"}, justification = "https://github.com/spotbugs/spotbugs/issues/1539 and doesn't need to be secure, we're just not hardcoding a 'wrong' password")
+ private static String generatePassword() {
+ String password = new Random().ints(20, 33, 127).mapToObj(i -> (char) i)
+ .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();
+ return password;
+ }
+
@Extension @Symbol("local")
public static final class DescriptorImpl extends Descriptor {
@NonNull
diff --git a/core/src/main/java/hudson/security/LegacyAuthorizationStrategy.java b/core/src/main/java/hudson/security/LegacyAuthorizationStrategy.java
index f9285262d9ac..39144b65b291 100644
--- a/core/src/main/java/hudson/security/LegacyAuthorizationStrategy.java
+++ b/core/src/main/java/hudson/security/LegacyAuthorizationStrategy.java
@@ -28,7 +28,7 @@
import hudson.Extension;
import hudson.model.Descriptor;
import java.util.Collection;
-import java.util.Collections;
+import java.util.Set;
import jenkins.model.Jenkins;
import org.acegisecurity.acls.sid.GrantedAuthoritySid;
import org.jenkinsci.Symbol;
@@ -55,7 +55,7 @@ public ACL getRootACL() {
@Override
public Collection getGroups() {
- return Collections.singleton("admin");
+ return Set.of("admin");
}
@Extension @Symbol("legacy")
diff --git a/core/src/main/java/hudson/security/Permission.java b/core/src/main/java/hudson/security/Permission.java
index 088266ae360f..05d68d10ba62 100644
--- a/core/src/main/java/hudson/security/Permission.java
+++ b/core/src/main/java/hudson/security/Permission.java
@@ -27,10 +27,8 @@
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.model.Hudson;
-import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
-import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -150,7 +148,7 @@ public Permission(@NonNull PermissionGroup group, @NonNull String name,
this.description = description;
this.impliedBy = impliedBy;
this.enabled = enable;
- this.scopes = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(scopes)));
+ this.scopes = Set.of(scopes);
this.id = owner.getName() + '.' + name;
group.add(this);
diff --git a/core/src/main/java/hudson/security/PermissionScope.java b/core/src/main/java/hudson/security/PermissionScope.java
index 126d158cad07..60eae23ea99b 100644
--- a/core/src/main/java/hudson/security/PermissionScope.java
+++ b/core/src/main/java/hudson/security/PermissionScope.java
@@ -32,9 +32,6 @@
import hudson.model.ModelObject;
import hudson.model.Node;
import hudson.model.Run;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
import java.util.Set;
import jenkins.model.Jenkins;
@@ -71,7 +68,7 @@ public final class PermissionScope {
public PermissionScope(Class extends ModelObject> modelClass, PermissionScope... containers) {
this.modelClass = modelClass;
- this.containers = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(containers)));
+ this.containers = Set.of(containers);
}
/**
diff --git a/core/src/main/java/hudson/security/SecurityRealm.java b/core/src/main/java/hudson/security/SecurityRealm.java
index f2ad1fa7b63d..ca62a4d3fe0e 100644
--- a/core/src/main/java/hudson/security/SecurityRealm.java
+++ b/core/src/main/java/hudson/security/SecurityRealm.java
@@ -37,11 +37,10 @@
import hudson.util.DescriptorList;
import hudson.util.PluginServletFilter;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -617,7 +616,7 @@ public Filter createFilter(FilterConfig filterConfig) {
protected final List commonFilters() {
// like Jenkins.ANONYMOUS:
- AnonymousAuthenticationFilter apf = new AnonymousAuthenticationFilter("anonymous", "anonymous", Collections.singletonList(new SimpleGrantedAuthority("anonymous")));
+ AnonymousAuthenticationFilter apf = new AnonymousAuthenticationFilter("anonymous", "anonymous", List.of(new SimpleGrantedAuthority("anonymous")));
ExceptionTranslationFilter etf = new ExceptionTranslationFilter(new HudsonAuthenticationEntryPoint("/" + getLoginUrl() + "?from={0}"));
etf.setAccessDeniedHandler(new AccessDeniedHandlerImpl());
UnwrapSecurityExceptionFilter usef = new UnwrapSecurityExceptionFilter();
@@ -640,7 +639,7 @@ protected final List commonFilters() {
*/
@Restricted(DoNotUse.class)
public static String getFrom() {
- String from = null, returnValue = null;
+ String from = null;
final StaplerRequest request = Stapler.getCurrentRequest();
// Try to obtain a return point from the query parameter
@@ -664,9 +663,7 @@ public static String getFrom() {
from = StringUtils.defaultIfBlank(from, "/").trim();
// Encode the return value
- try {
- returnValue = URLEncoder.encode(from, "UTF-8");
- } catch (UnsupportedEncodingException e) { }
+ String returnValue = URLEncoder.encode(from, StandardCharsets.UTF_8);
// Return encoded value or at least "/" in the case exception occurred during encode()
// or if the encoded content is blank value
diff --git a/core/src/main/java/hudson/security/WhoAmI.java b/core/src/main/java/hudson/security/WhoAmI.java
index 784cef76f1b8..9bde9c17e5af 100644
--- a/core/src/main/java/hudson/security/WhoAmI.java
+++ b/core/src/main/java/hudson/security/WhoAmI.java
@@ -6,9 +6,6 @@
import hudson.model.Api;
import hudson.model.UnprotectedRootAction;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
@@ -31,11 +28,11 @@
@Extension @Symbol("whoAmI")
@ExportedBean
public class WhoAmI implements UnprotectedRootAction {
- private static final Set dangerousHeaders = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
+ private static final Set dangerousHeaders = Set.of(
"cookie",
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#Authentication
"authorization", "www-authenticate", "proxy-authenticate", "proxy-authorization"
- )));
+ );
public Api getApi() {
return new Api(this);
diff --git a/core/src/main/java/hudson/slaves/Channels.java b/core/src/main/java/hudson/slaves/Channels.java
index b5f5fadcceea..687ba60c300d 100644
--- a/core/src/main/java/hudson/slaves/Channels.java
+++ b/core/src/main/java/hudson/slaves/Channels.java
@@ -40,6 +40,7 @@
import hudson.util.StreamCopyThread;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
+import java.io.File;
import java.io.IOError;
import java.io.IOException;
import java.io.InputStream;
@@ -47,6 +48,7 @@
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
+import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
@@ -181,7 +183,9 @@ public synchronized void join() throws InterruptedException {
* @return
* never null
* @since 1.300
+ * @deprecated removed without replacement
*/
+ @Deprecated
public static Channel newJVM(String displayName, TaskListener listener, FilePath workDir, ClasspathBuilder classpath, Map systemProperties) throws IOException {
JVMBuilder vmb = new JVMBuilder();
vmb.systemProperties(systemProperties);
@@ -212,7 +216,9 @@ public static Channel newJVM(String displayName, TaskListener listener, FilePath
* @return
* never null
* @since 1.361
+ * @deprecated removed without replacement
*/
+ @Deprecated
public static Channel newJVM(String displayName, TaskListener listener, JVMBuilder vmb, FilePath workDir, ClasspathBuilder classpath) throws IOException {
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress("localhost", 0));
@@ -223,7 +229,7 @@ public static Channel newJVM(String displayName, TaskListener listener, JVMBuild
vmb.mainClass(Launcher.class);
if (classpath != null)
- vmb.args().add("-cp").add(classpath);
+ Arrays.stream(classpath.toString().split(File.pathSeparator)).forEach(arg -> vmb.classpath().add(arg));
vmb.args().add("-connectTo", "localhost:" + serverSocket.getLocalPort());
listener.getLogger().println("Starting " + displayName);
diff --git a/core/src/main/java/hudson/slaves/JNLPLauncher.java b/core/src/main/java/hudson/slaves/JNLPLauncher.java
index 1098769b8146..e8c456a95929 100644
--- a/core/src/main/java/hudson/slaves/JNLPLauncher.java
+++ b/core/src/main/java/hudson/slaves/JNLPLauncher.java
@@ -34,6 +34,7 @@
import hudson.model.TaskListener;
import hudson.util.FormValidation;
import jenkins.model.Jenkins;
+import jenkins.model.identity.InstanceIdentityProvider;
import jenkins.slaves.RemotingWorkDirSettings;
import jenkins.util.SystemProperties;
import jenkins.websocket.WebSockets;
@@ -251,6 +252,9 @@ public FormValidation doCheckWebSocket(@QueryParameter boolean webSocket, @Query
if (Jenkins.get().getTcpSlaveAgentListener() == null) {
return FormValidation.error("Either WebSocket mode is selected, or the TCP port for inbound agents must be enabled");
}
+ if (InstanceIdentityProvider.RSA.getCertificate() == null || InstanceIdentityProvider.RSA.getPrivateKey() == null) {
+ return FormValidation.error("You must install the instance-identity plugin to use inbound agents in TCP mode");
+ }
}
return FormValidation.ok();
}
diff --git a/core/src/main/java/hudson/slaves/NodeProvisioner.java b/core/src/main/java/hudson/slaves/NodeProvisioner.java
index 87a0d7d45c1a..d1a6a10612da 100644
--- a/core/src/main/java/hudson/slaves/NodeProvisioner.java
+++ b/core/src/main/java/hudson/slaves/NodeProvisioner.java
@@ -45,7 +45,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutionException;
@@ -319,7 +318,7 @@ private void update() {
if (provisioningState != null) {
List strategies = Jenkins.get().getExtensionList(Strategy.class);
for (Strategy strategy : strategies.isEmpty()
- ? Collections.singletonList(new StandardStrategyImpl())
+ ? List.of(new StandardStrategyImpl())
: strategies) {
LOGGER.log(Level.FINER, "Consulting {0} provisioning strategy with state {1}",
new Object[]{strategy, provisioningState});
diff --git a/core/src/main/java/hudson/tasks/BuildStepCompatibilityLayer.java b/core/src/main/java/hudson/tasks/BuildStepCompatibilityLayer.java
index 5feacaf28db5..e71e244a11f0 100644
--- a/core/src/main/java/hudson/tasks/BuildStepCompatibilityLayer.java
+++ b/core/src/main/java/hudson/tasks/BuildStepCompatibilityLayer.java
@@ -40,6 +40,7 @@
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
import jenkins.tasks.SimpleBuildStep;
/**
@@ -103,7 +104,7 @@ public Collection extends Action> getProjectActions(AbstractProject, ?> proj
// delegate to getJobAction (singular) for backward compatible behavior
Action a = getProjectAction(project);
if (a == null) return Collections.emptyList();
- return Collections.singletonList(a);
+ return List.of(a);
}
diff --git a/core/src/main/java/hudson/tasks/BuildTrigger.java b/core/src/main/java/hudson/tasks/BuildTrigger.java
index 08c3a147f8d7..f6f17dab490c 100644
--- a/core/src/main/java/hudson/tasks/BuildTrigger.java
+++ b/core/src/main/java/hudson/tasks/BuildTrigger.java
@@ -278,7 +278,7 @@ public static boolean execute(AbstractBuild build, BuildListener listener) {
List downstreamProjects = new ArrayList<>(
graph.getDownstreamDependencies(build.getProject()));
// Sort topologically
- downstreamProjects.sort(new Comparator() {
+ downstreamProjects.sort(new Comparator<>() {
@Override
public int compare(Dependency lhs, Dependency rhs) {
// Swapping lhs/rhs to get reverse sort:
diff --git a/core/src/main/java/hudson/tasks/BuildWrapper.java b/core/src/main/java/hudson/tasks/BuildWrapper.java
index e6fc50da73f3..c4b7aa86a2d0 100644
--- a/core/src/main/java/hudson/tasks/BuildWrapper.java
+++ b/core/src/main/java/hudson/tasks/BuildWrapper.java
@@ -44,6 +44,7 @@
import java.io.OutputStream;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import jenkins.model.Jenkins;
@@ -291,7 +292,7 @@ public Collection extends Action> getProjectActions(AbstractProject job) {
// delegate to getJobAction (singular) for backward compatible behavior
Action a = getProjectAction(job);
if (a == null) return Collections.emptyList();
- return Collections.singletonList(a);
+ return List.of(a);
}
/**
diff --git a/core/src/main/java/hudson/tasks/Maven.java b/core/src/main/java/hudson/tasks/Maven.java
index beee7b8624d5..404c21410d6f 100644
--- a/core/src/main/java/hudson/tasks/Maven.java
+++ b/core/src/main/java/hudson/tasks/Maven.java
@@ -693,7 +693,7 @@ public String getDisplayName() {
@Override
public List extends ToolInstaller> getDefaultInstallers() {
- return Collections.singletonList(new MavenInstaller(null));
+ return List.of(new MavenInstaller(null));
}
// overriding them for backward compatibility.
diff --git a/core/src/main/java/hudson/tools/DownloadFromUrlInstaller.java b/core/src/main/java/hudson/tools/DownloadFromUrlInstaller.java
index 8df8f6c491a8..5d7f4c0c024f 100644
--- a/core/src/main/java/hudson/tools/DownloadFromUrlInstaller.java
+++ b/core/src/main/java/hudson/tools/DownloadFromUrlInstaller.java
@@ -103,7 +103,7 @@ public FilePath performInstallation(ToolInstallation tool, Node node, TaskListen
* @param root
* The directory that contains the extracted archive. This directory contains nothing but the
* extracted archive. For example, if the user installed
- * https://archive.apache.org/dist/ant/binaries/jakarta-ant-1.1.zip , this directory would contain
+ * jakarta-ant-1.1.zip , this directory would contain
* a single directory "jakarta-ant".
*
* @return
diff --git a/core/src/main/java/hudson/triggers/SCMTrigger.java b/core/src/main/java/hudson/triggers/SCMTrigger.java
index 0c054c70bd73..a078cde4ff2f 100644
--- a/core/src/main/java/hudson/triggers/SCMTrigger.java
+++ b/core/src/main/java/hudson/triggers/SCMTrigger.java
@@ -57,6 +57,7 @@
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.charset.Charset;
+import java.nio.file.Files;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
@@ -79,7 +80,6 @@
import jenkins.triggers.SCMTriggerItem;
import jenkins.util.SystemProperties;
import net.sf.json.JSONObject;
-import org.apache.commons.io.FileUtils;
import org.apache.commons.jelly.XMLOutput;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.Symbol;
@@ -205,7 +205,7 @@ public Collection extends Action> getProjectActions() {
return Collections.emptyList();
}
- return Collections.singleton(new SCMAction());
+ return Set.of(new SCMAction());
}
/**
@@ -717,7 +717,7 @@ public static class SCMTriggerCause extends Cause {
public SCMTriggerCause(File logFile) throws IOException {
// TODO: charset of this log file?
- this(FileUtils.readFileToString(logFile));
+ this(Files.readString(Util.fileToPath(logFile), Charset.defaultCharset()));
}
public SCMTriggerCause(String pollingLog) {
@@ -743,7 +743,7 @@ public void onAddedTo(Run build) {
this.run = build;
try {
BuildAction a = new BuildAction(build);
- FileUtils.writeStringToFile(a.getPollingLogFile(), pollingLog);
+ Files.writeString(Util.fileToPath(a.getPollingLogFile()), pollingLog, Charset.defaultCharset());
build.replaceAction(a);
} catch (IOException e) {
LOGGER.log(WARNING, "Failed to persist the polling log", e);
diff --git a/core/src/main/java/hudson/triggers/SafeTimerTask.java b/core/src/main/java/hudson/triggers/SafeTimerTask.java
index db07c96867df..5a261d0e9a2e 100644
--- a/core/src/main/java/hudson/triggers/SafeTimerTask.java
+++ b/core/src/main/java/hudson/triggers/SafeTimerTask.java
@@ -24,6 +24,7 @@
package hudson.triggers;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.model.AperiodicWork;
import hudson.model.AsyncAperiodicWork;
import hudson.model.AsyncPeriodicWork;
@@ -47,6 +48,7 @@
* @author Kohsuke Kawaguchi
* @since 1.124
*/
+@SuppressFBWarnings(value = "THROWS_METHOD_THROWS_CLAUSE_BASIC_EXCEPTION", justification = "TODO needs triage")
public abstract class SafeTimerTask extends TimerTask {
/**
diff --git a/core/src/main/java/hudson/triggers/Trigger.java b/core/src/main/java/hudson/triggers/Trigger.java
index 896143cba390..bbe02fcb8d00 100644
--- a/core/src/main/java/hudson/triggers/Trigger.java
+++ b/core/src/main/java/hudson/triggers/Trigger.java
@@ -150,7 +150,7 @@ public Collection extends Action> getProjectActions() {
// delegate to getJobAction (singular) for backward compatible behavior
Action a = getProjectAction();
if (a == null) return Collections.emptyList();
- return Collections.singletonList(a);
+ return List.of(a);
}
@Override
diff --git a/core/src/main/java/hudson/util/ArgumentListBuilder.java b/core/src/main/java/hudson/util/ArgumentListBuilder.java
index 41de0c6cb519..d75377e919f7 100644
--- a/core/src/main/java/hudson/util/ArgumentListBuilder.java
+++ b/core/src/main/java/hudson/util/ArgumentListBuilder.java
@@ -248,7 +248,7 @@ public ArgumentListBuilder addKeyValuePairsFromPropertyString(String prefix, Str
*/
private static VariableResolver propertiesGeneratingResolver(final VariableResolver original) {
- return new VariableResolver() {
+ return new VariableResolver<>() {
@Override
public String resolve(String name) {
diff --git a/core/src/main/java/hudson/util/BootFailure.java b/core/src/main/java/hudson/util/BootFailure.java
index 6e96e39e778b..a460ffea148e 100644
--- a/core/src/main/java/hudson/util/BootFailure.java
+++ b/core/src/main/java/hudson/util/BootFailure.java
@@ -8,7 +8,7 @@
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
-import java.text.DateFormat;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -64,7 +64,8 @@ protected List loadAttempts(File home) {
if (f.exists()) {
try (BufferedReader failureFileReader = Files.newBufferedReader(f.toPath(), Charset.defaultCharset())) {
String line;
- DateFormat df = DateFormat.getDateInstance();
+ // WebAppMain.recordBootAttempt uses Date.toString when writing, so that is the format we must parse.
+ SimpleDateFormat df = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
while ((line = failureFileReader.readLine()) != null) {
try {
dates.add(df.parse(line));
diff --git a/core/src/main/java/hudson/util/ChunkedInputStream.java b/core/src/main/java/hudson/util/ChunkedInputStream.java
index 865251c2f1ca..cfe61a17fcf1 100644
--- a/core/src/main/java/hudson/util/ChunkedInputStream.java
+++ b/core/src/main/java/hudson/util/ChunkedInputStream.java
@@ -261,7 +261,7 @@ private static int getChunkSizeFromInputStream(final InputStream in)
}
//parse data
- String dataString = new String(baos.toByteArray(), StandardCharsets.US_ASCII);
+ String dataString = baos.toString(StandardCharsets.US_ASCII);
int separator = dataString.indexOf(';');
dataString = separator > 0
? dataString.substring(0, separator).trim()
diff --git a/core/src/main/java/hudson/util/ClassLoaderSanityThreadFactory.java b/core/src/main/java/hudson/util/ClassLoaderSanityThreadFactory.java
index fe05e9ac7c8d..07a503f666aa 100644
--- a/core/src/main/java/hudson/util/ClassLoaderSanityThreadFactory.java
+++ b/core/src/main/java/hudson/util/ClassLoaderSanityThreadFactory.java
@@ -4,9 +4,9 @@
import java.util.concurrent.TimeUnit;
/**
- * Explicitly sets the {@link Thread#contextClassLoader} for threads it creates to its own classloader.
+ * Explicitly sets the {@link Thread#setContextClassLoader} for threads it creates to its own classloader.
* This avoids issues where threads are lazily created (ex by invoking {@link java.util.concurrent.ScheduledExecutorService#schedule(Runnable, long, TimeUnit)})
- * in a context where they would receive a customized {@link Thread#contextClassLoader} that was never meant to be used.
+ * in a context where they would receive a customized {@link Thread#getContextClassLoader} that was never meant to be used.
*
* Commonly this is a problem for Groovy use, where this may result in memory leaks.
* @see JENKINS-49206
diff --git a/core/src/main/java/hudson/util/ColorPalette.java b/core/src/main/java/hudson/util/ColorPalette.java
index d3aee355a927..10c22e997c11 100644
--- a/core/src/main/java/hudson/util/ColorPalette.java
+++ b/core/src/main/java/hudson/util/ColorPalette.java
@@ -26,8 +26,6 @@
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.awt.Color;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
@@ -48,12 +46,12 @@ public class ColorPalette {
* Color list usable for generating line charts.
*/
@SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "used in several plugins")
- public static List LINE_GRAPH = Collections.unmodifiableList(Arrays.asList(
+ public static List LINE_GRAPH = List.of(
new Color(0xCC0000),
new Color(0x3465a4),
new Color(0x73d216),
new Color(0xedd400)
- ));
+ );
/**
* Applies {@link #LINE_GRAPH} colors to the given renderer.
diff --git a/core/src/main/java/hudson/util/ConsistentHash.java b/core/src/main/java/hudson/util/ConsistentHash.java
index 243f19670936..25ddc3b7515b 100644
--- a/core/src/main/java/hudson/util/ConsistentHash.java
+++ b/core/src/main/java/hudson/util/ConsistentHash.java
@@ -54,8 +54,8 @@
* as increase/decrease of the replicas.
*
*
- * See http://en.wikipedia.org/wiki/Consistent_hashing for references, and
- * http://tom-e-white.com/2007/11/consistent-hashing.html is probably a reasonable depiction.
+ * See the Wikipedia page for references, and
+ * this blog post is probably a reasonable depiction.
* If we trust his experiments, creating 100 replicas will reduce the stddev to 10% of the mean for 10 nodes.
*
* @author Kohsuke Kawaguchi
@@ -145,7 +145,7 @@ T lookup(int queryPoint) {
*/
Iterator list(int queryPoint) {
final int start = index(queryPoint);
- return new DuplicateFilterIterator<>(new Iterator() {
+ return new DuplicateFilterIterator<>(new Iterator<>() {
int pos = 0;
@Override
diff --git a/core/src/main/java/hudson/util/CopyOnWriteList.java b/core/src/main/java/hudson/util/CopyOnWriteList.java
index b9eaad8c86fc..77bc05b4bf12 100644
--- a/core/src/main/java/hudson/util/CopyOnWriteList.java
+++ b/core/src/main/java/hudson/util/CopyOnWriteList.java
@@ -96,8 +96,9 @@ public synchronized boolean remove(E e) {
@Override
public Iterator iterator() {
final Iterator extends E> itr = core.iterator();
- return new Iterator() {
+ return new Iterator<>() {
private E last;
+
@Override
public boolean hasNext() {
return itr.hasNext();
diff --git a/core/src/main/java/hudson/util/DoubleLaunchChecker.java b/core/src/main/java/hudson/util/DoubleLaunchChecker.java
index f42004a1d670..d541452ca141 100644
--- a/core/src/main/java/hudson/util/DoubleLaunchChecker.java
+++ b/core/src/main/java/hudson/util/DoubleLaunchChecker.java
@@ -28,22 +28,20 @@
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import hudson.Util;
import hudson.init.Initializer;
import hudson.triggers.SafeTimerTask;
import java.io.File;
import java.io.IOException;
-import java.lang.management.ManagementFactory;
-import java.lang.reflect.Method;
import java.nio.charset.Charset;
+import java.nio.file.Files;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import jenkins.model.Jenkins;
import jenkins.util.Timer;
-import org.apache.commons.io.FileUtils;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.interceptor.RequirePOST;
@@ -62,10 +60,6 @@
* this file. In this way, while we cannot detect the problem right away, within a reasonable time frame
* we can detect the collision.
*
- *
- * More traditional way of doing this is to use a lock file with PID in it, but unfortunately in Java,
- * there's no reliable way to obtain PID.
- *
* @author Kohsuke Kawaguchi
* @since 1.178
*/
@@ -103,19 +97,20 @@ protected void execute() {
long t = timestampFile.lastModified();
if (t != 0 && lastWriteTime != 0 && t != lastWriteTime && !ignore) {
try {
- collidingId = FileUtils.readFileToString(timestampFile, Charset.defaultCharset());
+ collidingId = Files.readString(Util.fileToPath(timestampFile), Charset.defaultCharset());
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Failed to read collision file", e);
}
// we noticed that someone else have updated this file.
// switch GUI to display this error.
+ // TODO seems drastic; could this just be switched to an AdministrativeMonitor?
Jenkins.get().servletContext.setAttribute("app", this);
LOGGER.severe("Collision detected. timestamp=" + t + ", expected=" + lastWriteTime);
// we need to continue updating this file, so that the other Hudson would notice the problem, too.
}
try {
- FileUtils.writeStringToFile(timestampFile, getId(), Charset.defaultCharset());
+ Files.writeString(Util.fileToPath(timestampFile), getId(), Charset.defaultCharset());
lastWriteTime = timestampFile.lastModified();
} catch (IOException e) {
// if failed to write, err on the safe side and assume things are OK.
@@ -129,20 +124,7 @@ protected void execute() {
* Figures out a string that identifies this instance of Hudson.
*/
public String getId() {
- Jenkins h = Jenkins.get();
-
- // in servlet 2.5, we can get the context path
- String contextPath = "";
- try {
- Method m = ServletContext.class.getMethod("getContextPath");
- contextPath = " contextPath=\"" + m.invoke(h.servletContext) + "\"";
- } catch (RuntimeException e) {
- throw e;
- } catch (Exception e) {
- // maybe running with Servlet 2.4
- }
-
- return h.hashCode() + contextPath + " at " + ManagementFactory.getRuntimeMXBean().getName();
+ return Long.toString(ProcessHandle.current().pid());
}
public String getCollidingId() {
@@ -154,7 +136,7 @@ public String getCollidingId() {
*/
public void schedule() {
// randomize the scheduling so that multiple Hudson instances will write at the file at different time
- long MINUTE = 1000 * 60;
+ long MINUTE = 1000 * 60; // TODO use TimeUnit.MINUTE.toMillis
Timer.get()
.schedule(new SafeTimerTask() {
@@ -167,6 +149,7 @@ protected void doRun() {
@Initializer(after = JOB_CONFIG_ADAPTED)
public static void init() {
+ // TODO AperiodicWork would be more idiomatic
new DoubleLaunchChecker().schedule();
}
diff --git a/core/src/main/java/hudson/util/FormFieldValidator.java b/core/src/main/java/hudson/util/FormFieldValidator.java
index 4453b60be333..f4ec7899a5b4 100644
--- a/core/src/main/java/hudson/util/FormFieldValidator.java
+++ b/core/src/main/java/hudson/util/FormFieldValidator.java
@@ -230,14 +230,12 @@ private void _errorWithMarkup(String message, String cssClass) throws IOExceptio
ok();
} else {
response.setContentType("text/html;charset=UTF-8");
- // 1x16 spacer needed for IE since it doesn't support min-height
if (APPLY_CONTENT_SECURITY_POLICY_HEADERS) {
for (String header : new String[]{"Content-Security-Policy", "X-WebKit-CSP", "X-Content-Security-Policy"}) {
response.setHeader(header, "sandbox; default-src 'none';");
}
}
- response.getWriter().print("
![](" +
- request.getContextPath() + Jenkins.RESOURCE_PATH + "/images/none.gif)
" +
+ response.getWriter().print("
" +
message + "
");
}
}
diff --git a/core/src/main/java/hudson/util/FormFillFailure.java b/core/src/main/java/hudson/util/FormFillFailure.java
index 48cab2ce5fd9..5ebd0d5a31e6 100644
--- a/core/src/main/java/hudson/util/FormFillFailure.java
+++ b/core/src/main/java/hudson/util/FormFillFailure.java
@@ -31,7 +31,6 @@
import java.util.Locale;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
-import jenkins.model.Jenkins;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
@@ -95,7 +94,7 @@ private static FormFillFailure _error(FormValidation.Kind kind, Throwable e, Str
}
return _errorWithMarkup(Util.escape(message) +
- "
"
+ " "
+ Messages.FormValidation_Error_Details()
+ ""
+ Util.escape(Functions.printThrowable(e)) +
@@ -137,9 +136,7 @@ public String renderHtml() {
if (req == null) { // being called from some other context
return message;
}
- // 1x16 spacer needed for IE since it doesn't support min-height
- return "![](" +
- req.getContextPath() + Jenkins.RESOURCE_PATH + "/images/none.gif)
" +
+ return "
" +
message + "
";
}
diff --git a/core/src/main/java/hudson/util/FormValidation.java b/core/src/main/java/hudson/util/FormValidation.java
index 44f81fb1d44d..931e47ccf0ed 100644
--- a/core/src/main/java/hudson/util/FormValidation.java
+++ b/core/src/main/java/hudson/util/FormValidation.java
@@ -198,7 +198,7 @@ private static FormValidation _error(Kind kind, Throwable e, String message) {
if (e == null) return _errorWithMarkup(Util.escape(message), kind);
return _errorWithMarkup(Util.escape(message) +
- "
"
+ " "
+ Messages.FormValidation_Error_Details()
+ ""
+ Util.escape(Functions.printThrowable(e)) +
@@ -272,9 +272,7 @@ public String renderHtml() {
if (req == null) { // being called from some other context
return message;
}
- // 1x16 spacer needed for IE since it doesn't support min-height
- return "![](" +
- req.getContextPath() + Jenkins.RESOURCE_PATH + "/images/none.gif)
" +
+ return "
" +
message + "
";
}
diff --git a/core/src/main/java/hudson/util/Futures.java b/core/src/main/java/hudson/util/Futures.java
index c8c5c5182b60..8e9bf7081ed7 100644
--- a/core/src/main/java/hudson/util/Futures.java
+++ b/core/src/main/java/hudson/util/Futures.java
@@ -37,7 +37,7 @@ public class Futures {
* Creates a {@link Future} instance that already has its value pre-computed.
*/
public static
Future precomputed(final T value) {
- return new Future() {
+ return new Future<>() {
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
diff --git a/core/src/main/java/hudson/util/HeapSpaceStringConverter.java b/core/src/main/java/hudson/util/HeapSpaceStringConverter.java
index 535d9bd535ab..31fe944bd938 100644
--- a/core/src/main/java/hudson/util/HeapSpaceStringConverter.java
+++ b/core/src/main/java/hudson/util/HeapSpaceStringConverter.java
@@ -34,7 +34,7 @@
*
* Since XStream 1.3 it use a WeakHashMap cache to always use the same String instances, but
* this has also major problems with a single long living XStream instance (as we have in Jenkins)
- * See https://x-stream.github.io/jira/604/
+ * See XSTR-604.
*
*
* Use this to avoid that (instead those strings will
diff --git a/core/src/main/java/hudson/util/InterceptingProxy.java b/core/src/main/java/hudson/util/InterceptingProxy.java
index 3ab7ebb0b318..af368ac5bf5e 100644
--- a/core/src/main/java/hudson/util/InterceptingProxy.java
+++ b/core/src/main/java/hudson/util/InterceptingProxy.java
@@ -1,5 +1,6 @@
package hudson.util;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -10,6 +11,7 @@
*
* @author Kohsuke Kawaguchi
*/
+@SuppressFBWarnings(value = "THROWS_METHOD_THROWS_CLAUSE_THROWABLE", justification = "TODO needs triage")
public abstract class InterceptingProxy {
/**
* Intercepts every method call.
diff --git a/core/src/main/java/hudson/util/Iterators.java b/core/src/main/java/hudson/util/Iterators.java
index ecf3da4a2941..f091404ee854 100644
--- a/core/src/main/java/hudson/util/Iterators.java
+++ b/core/src/main/java/hudson/util/Iterators.java
@@ -177,7 +177,7 @@ protected boolean filter(T t) {
public static Iterable reverse(final List lst) {
return () -> {
final ListIterator itr = lst.listIterator(lst.size());
- return new Iterator() {
+ return new Iterator<>() {
@Override
public boolean hasNext() {
return itr.hasPrevious();
@@ -205,7 +205,7 @@ public void remove() {
public static Iterable wrap(final Iterable base) {
return () -> {
final Iterator itr = base.iterator();
- return new Iterator() {
+ return new Iterator<>() {
@Override
public boolean hasNext() {
return itr.hasNext();
@@ -236,7 +236,7 @@ public static List sequence(final int start, int end, final int step) {
final int size = (end - start) / step;
if (size < 0) throw new IllegalArgumentException("List size is negative");
- return new AbstractList() {
+ return new AbstractList<>() {
@Override
public Integer get(int index) {
if (index < 0 || index >= size)
@@ -289,7 +289,7 @@ public static Iterable cast(Iterable extends T> itr) {
*/
@SuppressWarnings("unchecked")
public static Iterator subType(Iterator itr, final Class type) {
- return (Iterator) new FilterIterator(itr) {
+ return (Iterator) new FilterIterator<>(itr) {
@Override
protected boolean filter(U u) {
return type.isInstance(u);
@@ -301,7 +301,7 @@ protected boolean filter(U u) {
* Creates a read-only mutator that disallows {@link Iterator#remove()}.
*/
public static Iterator readOnly(final Iterator itr) {
- return new Iterator() {
+ return new Iterator<>() {
@Override
public boolean hasNext() {
return itr.hasNext();
@@ -334,7 +334,7 @@ public static Iterator removeNull(final Iterator itr) {
*/
@SafeVarargs
public static Iterable sequence(final Iterable extends T>... iterables) {
- return () -> new FlattenIterator>(ImmutableList.copyOf(iterables)) {
+ return () -> new FlattenIterator<>(ImmutableList.copyOf(iterables)) {
@Override
protected Iterator expand(Iterable extends T> iterable) {
return Iterators.cast(iterable).iterator();
@@ -346,8 +346,9 @@ protected Iterator expand(Iterable extends T> iterable) {
* Filters another iterator by eliminating duplicates.
*/
public static Iterator removeDups(Iterator iterator) {
- return new FilterIterator(iterator) {
+ return new FilterIterator<>(iterator) {
final Set found = new HashSet<>();
+
@Override
protected boolean filter(T t) {
return found.add(t);
@@ -374,7 +375,7 @@ public static Iterator sequence(Iterator extends T>... iterators) {
* @since 1.485
*/
public static Iterator limit(final Iterator extends T> base, final CountingPredicate super T> filter) {
- return new Iterator() {
+ return new Iterator<>() {
private T next;
private boolean end;
private int index = 0;
diff --git a/core/src/main/java/hudson/util/LogTaskListener.java b/core/src/main/java/hudson/util/LogTaskListener.java
index 267f8f7bf27f..20c6212924e9 100644
--- a/core/src/main/java/hudson/util/LogTaskListener.java
+++ b/core/src/main/java/hudson/util/LogTaskListener.java
@@ -31,7 +31,6 @@
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
-import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
import java.util.logging.LogRecord;
@@ -86,12 +85,7 @@ public void write(int b) throws IOException {
@Override
public void flush() throws IOException {
if (baos.size() > 0) {
- LogRecord lr;
- try {
- lr = new LogRecord(level, baos.toString(StandardCharsets.UTF_8.name()));
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError(e);
- }
+ LogRecord lr = new LogRecord(level, baos.toString(StandardCharsets.UTF_8));
lr.setLoggerName(logger.getName());
lr.setSourceClassName(caller.getClassName());
lr.setSourceMethodName(caller.getMethodName());
diff --git a/core/src/main/java/hudson/util/PackedMap.java b/core/src/main/java/hudson/util/PackedMap.java
index f070c368d6c9..21024256e2db 100644
--- a/core/src/main/java/hudson/util/PackedMap.java
+++ b/core/src/main/java/hudson/util/PackedMap.java
@@ -76,11 +76,11 @@ private PackedMap(Map extends K, ? extends V> src) {
}
}
- private final Set> entrySet = new AbstractSet>() {
+ private final Set> entrySet = new AbstractSet<>() {
@NonNull
@Override
public Iterator> iterator() {
- return new Iterator>() {
+ return new Iterator<>() {
int index = 0;
@Override
public boolean hasNext() {
@@ -92,7 +92,7 @@ public boolean hasNext() {
public Entry next() {
final K k = (K) kvpairs[index++];
final V v = (V) kvpairs[index++];
- return new Entry() {
+ return new Entry<>() {
@Override
public K getKey() {
return k;
@@ -149,7 +149,7 @@ public V get(Object key) {
@Override
@SuppressWarnings("unchecked")
public Collection values() {
- return new AbstractList() {
+ return new AbstractList<>() {
@Override
public V get(int index) {
return (V) kvpairs[index * 2];
diff --git a/core/src/main/java/hudson/util/PersistedList.java b/core/src/main/java/hudson/util/PersistedList.java
index ba9bf455d35a..5a93a69641c8 100644
--- a/core/src/main/java/hudson/util/PersistedList.java
+++ b/core/src/main/java/hudson/util/PersistedList.java
@@ -39,10 +39,7 @@
import java.lang.reflect.InvocationTargetException;
import java.util.AbstractList;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
@@ -202,7 +199,7 @@ protected void onModified() throws IOException {
}
// TODO until https://github.com/jenkinsci/jenkins-test-harness/pull/243 is widely adopted:
- private static final Set IGNORED_CLASSES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("org.jvnet.hudson.test.TestBuilder", "org.jvnet.hudson.test.TestNotifier")));
+ private static final Set IGNORED_CLASSES = Set.of("org.jvnet.hudson.test.TestBuilder", "org.jvnet.hudson.test.TestNotifier");
// (SingleFileSCM & ExtractResourceWithChangesSCM would also be nice to suppress, but they are not kept in a PersistedList.)
private static boolean ignoreSerializationErrors(Object o) {
diff --git a/core/src/main/java/hudson/util/ProcessTree.java b/core/src/main/java/hudson/util/ProcessTree.java
index 3e087106f90d..7169dec5b6a4 100644
--- a/core/src/main/java/hudson/util/ProcessTree.java
+++ b/core/src/main/java/hudson/util/ProcessTree.java
@@ -29,6 +29,7 @@
import static java.util.logging.Level.FINER;
import static java.util.logging.Level.FINEST;
+import com.google.common.primitives.Ints;
import com.sun.jna.LastErrorException;
import com.sun.jna.Memory;
import com.sun.jna.Native;
@@ -56,10 +57,6 @@
import java.io.ObjectStreamException;
import java.io.RandomAccessFile;
import java.io.Serializable;
-import java.io.UnsupportedEncodingException;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
@@ -70,7 +67,6 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.Optional;
import java.util.SortedMap;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@@ -79,7 +75,6 @@
import jenkins.agents.AgentComputerUtil;
import jenkins.security.SlaveToMasterCallable;
import jenkins.util.SystemProperties;
-import jenkins.util.java.JavaUtils;
import org.apache.commons.io.FileUtils;
import org.jenkinsci.remoting.SerializableOnlyOverRemoting;
import org.jvnet.winp.WinProcess;
@@ -757,7 +752,7 @@ abstract static class Unix extends Local {
@CheckForNull
@Override
public OSProcess get(@NonNull Process proc) {
- return get(UnixReflection.pid(proc));
+ return get(Ints.checkedCast(proc.pid()));
}
@Override
@@ -825,33 +820,20 @@ public void kill() throws InterruptedException {
private void kill(long deadline) throws InterruptedException {
if (getVeto() != null)
return;
- try {
- int pid = getPid();
- LOGGER.fine("Killing pid=" + pid);
- UnixReflection.destroy(pid);
- // after sending SIGTERM, wait for the process to cease to exist
- int sleepTime = 10; // initially we sleep briefly, then sleep up to 1sec
- File status = getFile("status");
- do {
- if (!status.exists()) {
- break; // status is gone, process therefore as well
- }
+ int pid = getPid();
+ LOGGER.fine("Killing pid=" + pid);
+ ProcessHandle.of(pid).ifPresent(ProcessHandle::destroy);
+ // after sending SIGTERM, wait for the process to cease to exist
+ int sleepTime = 10; // initially we sleep briefly, then sleep up to 1sec
+ File status = getFile("status");
+ do {
+ if (!status.exists()) {
+ break; // status is gone, process therefore as well
+ }
- Thread.sleep(sleepTime);
- sleepTime = Math.min(sleepTime * 2, 1000);
- } while (System.nanoTime() < deadline);
- } catch (IllegalAccessException e) {
- // this is impossible
- IllegalAccessError x = new IllegalAccessError();
- x.initCause(e);
- throw x;
- } catch (InvocationTargetException e) {
- // tunnel serious errors
- if (e.getTargetException() instanceof Error)
- throw (Error) e.getTargetException();
- // otherwise log and let go. I need to see when this happens
- LOGGER.log(Level.INFO, "Failed to terminate pid=" + getPid(), e);
- }
+ Thread.sleep(sleepTime);
+ sleepTime = Math.min(sleepTime * 2, 1000);
+ } while (System.nanoTime() < deadline);
killByKiller();
}
@@ -887,91 +869,6 @@ private void killRecursively(long deadline) throws InterruptedException {
public abstract List getArguments();
}
- //TODO: can be replaced by multi-release JAR
- /**
- * Reflection used in the Unix support.
- */
- private static final class UnixReflection {
- /**
- * Field to access the PID of the process.
- * Required for Java 8 and older JVMs.
- */
- private static final Field JAVA8_PID_FIELD;
-
- /**
- * Field to access the PID of the process.
- * Required for Java 9 and above until this is replaced by multi-release JAR.
- */
- private static final Method JAVA9_PID_METHOD;
-
- /**
- * Method to destroy a process, given pid.
- *
- * Looking at the JavaSE source code, this is using SIGTERM (15)
- */
- private static final Method JAVA8_DESTROY_PROCESS;
- private static final Method JAVA_9_PROCESSHANDLE_OF;
- private static final Method JAVA_9_PROCESSHANDLE_DESTROY;
-
- static {
- try {
- if (JavaUtils.isRunningWithPostJava8()) {
- Class> clazz = Process.class;
- JAVA9_PID_METHOD = clazz.getMethod("pid");
- JAVA8_PID_FIELD = null;
- Class> processHandleClazz = Class.forName("java.lang.ProcessHandle");
- JAVA_9_PROCESSHANDLE_OF = processHandleClazz.getMethod("of", long.class);
- JAVA_9_PROCESSHANDLE_DESTROY = processHandleClazz.getMethod("destroy");
- JAVA8_DESTROY_PROCESS = null;
- } else {
- Class> clazz = Class.forName("java.lang.UNIXProcess");
- JAVA8_PID_FIELD = clazz.getDeclaredField("pid");
- JAVA8_PID_FIELD.setAccessible(true);
- JAVA9_PID_METHOD = null;
-
- JAVA8_DESTROY_PROCESS = clazz.getDeclaredMethod("destroyProcess", int.class, boolean.class);
- JAVA8_DESTROY_PROCESS.setAccessible(true);
- JAVA_9_PROCESSHANDLE_OF = null;
- JAVA_9_PROCESSHANDLE_DESTROY = null;
- }
- } catch (ClassNotFoundException | NoSuchFieldException | NoSuchMethodException e) {
- throw new LinkageError("Cannot initialize reflection for Unix Processes", e);
- }
- }
-
- public static void destroy(int pid) throws IllegalAccessException,
- InvocationTargetException {
- if (JAVA8_DESTROY_PROCESS != null) {
- JAVA8_DESTROY_PROCESS.invoke(null, pid, false);
- } else {
- final Optional handle = (Optional) JAVA_9_PROCESSHANDLE_OF.invoke(null, pid);
- if (handle.isPresent()) {
- JAVA_9_PROCESSHANDLE_DESTROY.invoke(handle.get());
- }
- }
- }
-
- //TODO: We ideally need to update ProcessTree APIs to Support Long (JENKINS-53799).
- public static int pid(@NonNull Process proc) {
- try {
- if (JAVA8_PID_FIELD != null) {
- return JAVA8_PID_FIELD.getInt(proc);
- } else {
- long pid = (long) JAVA9_PID_METHOD.invoke(proc);
- if (pid > Integer.MAX_VALUE) {
- throw new IllegalAccessError("Java 9+ support error (JENKINS-53799). PID is out of Jenkins API bounds: " + pid);
- }
- return (int) pid;
- }
- } catch (IllegalAccessException | InvocationTargetException e) { // impossible
- IllegalAccessError x = new IllegalAccessError();
- x.initCause(e);
- throw x;
- }
- }
- }
-
-
static class Linux extends ProcfsUnix {
Linux(boolean vetoersExist) {
super(vetoersExist);
@@ -1352,12 +1249,7 @@ private String readLine(int fd, long addr, String prefix) throws IOException {
buf.write(ch);
addr++;
}
- String line;
- try {
- line = buf.toString(StandardCharsets.UTF_8.name());
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError(e);
- }
+ String line = buf.toString(StandardCharsets.UTF_8);
if (LOGGER.isLoggable(FINEST))
LOGGER.finest(prefix + " was " + line);
return line;
@@ -1628,12 +1520,7 @@ private String readLine(int fd, long addr, String prefix) throws IOException {
buf.write(ch);
addr++;
}
- String line;
- try {
- line = buf.toString(StandardCharsets.UTF_8.name());
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError(e);
- }
+ String line = buf.toString(StandardCharsets.UTF_8);
if (LOGGER.isLoggable(FINEST))
LOGGER.finest(prefix + " was " + line);
return line;
@@ -1801,11 +1688,7 @@ String readString() {
byte ch;
while (offset < length && (ch = getByte(offset++)) != '\0')
baos.write(ch);
- try {
- return baos.toString(StandardCharsets.UTF_8.name());
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError(e);
- }
+ return baos.toString(StandardCharsets.UTF_8);
}
void skip0() {
@@ -2119,11 +2002,7 @@ private void parse(Memory m, NativeLong size, Consumer consumer) {
while ((ch = m.getByte(offset++)) != '\0') {
baos.write(ch);
}
- try {
- consumer.accept(baos.toString(StandardCharsets.UTF_8.name()));
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError(e);
- }
+ consumer.accept(baos.toString(StandardCharsets.UTF_8));
baos.reset();
}
}
diff --git a/core/src/main/java/hudson/util/QueryParameterMap.java b/core/src/main/java/hudson/util/QueryParameterMap.java
index a187ae8ccabc..c4cf323d8ca8 100644
--- a/core/src/main/java/hudson/util/QueryParameterMap.java
+++ b/core/src/main/java/hudson/util/QueryParameterMap.java
@@ -24,8 +24,8 @@
package hudson.util;
-import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -57,16 +57,12 @@ public class QueryParameterMap {
*/
public QueryParameterMap(String queryString) {
if (queryString == null || queryString.length() == 0) return;
- try {
- for (String param : queryString.split("&")) {
- String[] kv = param.split("=");
- String key = URLDecoder.decode(kv[0], "UTF-8");
- String value = URLDecoder.decode(kv[1], "UTF-8");
- List values = store.computeIfAbsent(key, k -> new ArrayList<>());
- values.add(value);
- }
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError(e);
+ for (String param : queryString.split("&")) {
+ String[] kv = param.split("=");
+ String key = URLDecoder.decode(kv[0], StandardCharsets.UTF_8);
+ String value = URLDecoder.decode(kv[1], StandardCharsets.UTF_8);
+ List