loadPatternOverride() {
/**
* A class that uses a given set of regular expression patterns to determine if the class is blacklisted.
*/
- @SuppressFBWarnings(value = "REDOS", justification = "In an odd usage, this pattern is used to determine if another pattern matches it and not to match a string to it. REDOS doesn't apply.")
+ @SuppressFBWarnings(
+ value = "REDOS",
+ justification =
+ "In an odd usage, this pattern is used to determine if another pattern matches it and not to match a string to it. REDOS doesn't apply.")
private static final class RegExpClassFilter extends ClassFilter {
/**
@@ -248,8 +257,8 @@ private static final class RegExpClassFilter extends ClassFilter {
* {@link String#startsWith(String)} test and we can reduce CPU usage by performing that test explicitly as
* well as reduce GC pressure.
*/
- private static final Pattern OPTIMIZE1 = Pattern.compile(
- "^\\^(([\\p{L}_$][\\p{L}\\p{N}_$]*(\\.|\\[\\.\\])?)+)\\.\\*$");
+ private static final Pattern OPTIMIZE1 =
+ Pattern.compile("^\\^(([\\p{L}_$][\\p{L}\\p{N}_$]*(\\.|\\[\\.\\])?)+)\\.\\*$");
/**
* Any regex that is {@code ^\Qsome.package.name\E.*} is really just a {@link String#startsWith(String)}
@@ -288,9 +297,9 @@ void add(String pattern) throws ClassFilterException {
@Override
public boolean isBlacklisted(@NonNull String name) {
for (Object p : blacklistPatterns) {
- if (p instanceof Pattern && ((Pattern)p).matcher(name).matches()) {
+ if (p instanceof Pattern && ((Pattern) p).matcher(name).matches()) {
return true;
- } else if (p instanceof String && name.startsWith((String)p)) {
+ } else if (p instanceof String && name.startsWith((String) p)) {
return true;
}
}
diff --git a/src/main/java/hudson/remoting/ClassLoaderHolder.java b/src/main/java/hudson/remoting/ClassLoaderHolder.java
index a2cf72b3d..0b584aebd 100644
--- a/src/main/java/hudson/remoting/ClassLoaderHolder.java
+++ b/src/main/java/hudson/remoting/ClassLoaderHolder.java
@@ -14,7 +14,7 @@
* @since 2.12
*/
public class ClassLoaderHolder implements SerializableOnlyOverRemoting {
-
+
@CheckForNull
private transient ClassLoader classLoader;
@@ -22,8 +22,7 @@ public ClassLoaderHolder(@CheckForNull ClassLoader classLoader) {
this.classLoader = classLoader;
}
- public ClassLoaderHolder() {
- }
+ public ClassLoaderHolder() {}
@CheckForNull
public ClassLoader get() {
@@ -36,15 +35,18 @@ public void set(@CheckForNull ClassLoader classLoader) {
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
RemoteClassLoader.IClassLoader proxy = (RemoteClassLoader.IClassLoader) ois.readObject();
- classLoader = proxy==null ? null : getChannelForSerialization().importedClassLoaders.get(proxy);
+ classLoader = proxy == null
+ ? null
+ : getChannelForSerialization().importedClassLoaders.get(proxy);
}
- @SuppressFBWarnings(value = "DMI_NONSERIALIZABLE_OBJECT_WRITTEN",
+ @SuppressFBWarnings(
+ value = "DMI_NONSERIALIZABLE_OBJECT_WRITTEN",
justification = "RemoteClassLoader.export() produces a serializable wrapper class")
private void writeObject(ObjectOutputStream oos) throws IOException {
- if (classLoader==null)
+ if (classLoader == null) {
oos.writeObject(null);
- else {
+ } else {
RemoteClassLoader.IClassLoader proxy = RemoteClassLoader.export(classLoader, getChannelForSerialization());
oos.writeObject(proxy);
}
diff --git a/src/main/java/hudson/remoting/ClassicCommandTransport.java b/src/main/java/hudson/remoting/ClassicCommandTransport.java
index 9d4d1b669..50948a9d6 100644
--- a/src/main/java/hudson/remoting/ClassicCommandTransport.java
+++ b/src/main/java/hudson/remoting/ClassicCommandTransport.java
@@ -11,11 +11,11 @@
/**
* The default {@link CommandTransport} that has been used historically.
- *
+ *
*
* This implementation builds a {@link SynchronousCommandTransport} on top of a plain bi-directional byte stream.
* {@link Channel.Mode} support allows this to be built on 8-bit unsafe transport, such as telnet.
- *
+ *
* @author Kohsuke Kawaguchi
* @since 2.13
*/
@@ -27,17 +27,21 @@
* Transport level {@link InputStream} that we use only for diagnostics in case we detect stream
* corruption. Can be null.
*/
- private final @Nullable
- FlightRecorderInputStream rawIn;
+ private final @Nullable FlightRecorderInputStream rawIn;
/**
* See {@link CommandTransport#getUnderlyingStream()}
*/
private final OutputStream rawOut;
- /*package*/ ClassicCommandTransport(ObjectInputStream ois, ObjectOutputStream oos, @CheckForNull FlightRecorderInputStream rawIn, OutputStream rawOut, Capability remoteCapability) {
+ /*package*/ ClassicCommandTransport(
+ ObjectInputStream ois,
+ ObjectOutputStream oos,
+ @CheckForNull FlightRecorderInputStream rawIn,
+ OutputStream rawOut,
+ Capability remoteCapability) {
this.ois = ois;
this.oos = oos;
- this.rawIn= rawIn;
+ this.rawIn = rawIn;
this.rawOut = rawOut;
this.remoteCapability = remoteCapability;
}
@@ -49,9 +53,9 @@ public Capability getRemoteCapability() throws IOException {
@Override
public final void write(Command cmd, boolean last) throws IOException {
- cmd.writeTo(channel,oos);
+ cmd.writeTo(channel, oos);
// TODO notifyWrite using CountingOutputStream
- oos.flush(); // make sure the command reaches the other end.
+ oos.flush(); // make sure the command reaches the other end.
// unless this is the last command, have OOS and remote OIS forget all the objects we sent
// in this command. Otherwise it'll keep objects in memory unnecessarily.
@@ -59,8 +63,9 @@ public final void write(Command cmd, boolean last) throws IOException {
// ever sent. It is possible for our ReaderThread to receive the reflecting close call from the other side
// and close the output before the sending code gets to here.
// See the comment from jglick on JENKINS-3077 about what happens if we do oos.reset().
- if(!last)
+ if (!last) {
oos.reset();
+ }
}
@Override
@@ -73,10 +78,11 @@ public final Command read() throws IOException, ClassNotFoundException {
try {
Command cmd = Command.readFromObjectStream(channel, ois);
// TODO notifyRead using CountingInputStream
- if (rawIn!=null)
+ if (rawIn != null) {
rawIn.clear();
+ }
return cmd;
- } catch (RuntimeException | StreamCorruptedException e) {// see JENKINS-19046
+ } catch (RuntimeException | StreamCorruptedException e) { // see JENKINS-19046
throw diagnoseStreamCorruption(e);
}
}
@@ -86,14 +92,15 @@ public final Command read() throws IOException, ClassNotFoundException {
* This operation can block, so we'll use another thread to do this.
*/
private StreamCorruptedException diagnoseStreamCorruption(Exception e) {
- if (rawIn==null) {// no source of diagnostics information. can't diagnose.
- if (e instanceof StreamCorruptedException)
- return (StreamCorruptedException)e;
- else
- return (StreamCorruptedException)new StreamCorruptedException().initCause(e);
+ if (rawIn == null) { // no source of diagnostics information. can't diagnose.
+ if (e instanceof StreamCorruptedException) {
+ return (StreamCorruptedException) e;
+ } else {
+ return (StreamCorruptedException) new StreamCorruptedException().initCause(e);
+ }
}
- return rawIn.analyzeCrash(e,(channel!=null ? channel : this).toString());
+ return rawIn.analyzeCrash(e, (channel != null ? channel : this).toString());
}
@Override
diff --git a/src/main/java/hudson/remoting/Command.java b/src/main/java/hudson/remoting/Command.java
index 5004b1710..d7f1a1355 100644
--- a/src/main/java/hudson/remoting/Command.java
+++ b/src/main/java/hudson/remoting/Command.java
@@ -1,18 +1,18 @@
/*
* The MIT License
- *
+ *
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -43,7 +43,7 @@
*
* At this level, remoting of class files are not provided, so both {@link Channel}s
* need to have the definition of {@link Command}-implementation.
- *
+ *
* @author Kohsuke Kawaguchi
* @see Channel.Listener#onRead
* @see Channel.Listener#onWrite
@@ -76,10 +76,11 @@ public abstract class Command implements Serializable {
* transferred.
*/
Command(boolean recordCreatedAt) {
- if(recordCreatedAt)
+ if (recordCreatedAt) {
this.createdAt = new Source();
- else
+ } else {
this.createdAt = null;
+ }
}
/**
@@ -91,7 +92,6 @@ public abstract class Command implements Serializable {
*/
abstract void execute(Channel channel) throws ExecutionException;
-
/**
* Chains the {@link #createdAt} cause.
* It will happen if and only if cause recording is enabled.
@@ -102,7 +102,7 @@ final void chainCause(@CheckForNull Throwable initCause) {
createdAt.initCause(initCause);
}
}
-
+
/** Consider calling {@link Channel#notifyWrite} afterwards. */
void writeTo(Channel channel, ObjectOutputStream oos) throws IOException {
Channel old = Channel.setCurrent(channel);
@@ -138,20 +138,22 @@ public static Command readFrom(@NonNull Channel channel, @NonNull byte[] payload
*/
/*package*/ static Command readFrom(@NonNull Channel channel, @NonNull InputStream istream, int payloadSize)
throws IOException, ClassNotFoundException {
- Command cmd = Command.readFromObjectStream(channel, new ObjectInputStreamEx(
- istream,
- channel.baseClassLoader,channel.classFilter));
+ Command cmd = Command.readFromObjectStream(
+ channel, new ObjectInputStreamEx(istream, channel.baseClassLoader, channel.classFilter));
channel.notifyRead(cmd, payloadSize);
return cmd;
}
-
/** Consider calling {@link Channel#notifyRead} afterwards. */
- @SuppressFBWarnings(value = "OBJECT_DESERIALIZATION", justification = "Used for sending commands between authorized agent and server. Class filtering is done through JEP-200.")
- static Command readFromObjectStream(Channel channel, ObjectInputStream ois) throws IOException, ClassNotFoundException {
+ @SuppressFBWarnings(
+ value = "OBJECT_DESERIALIZATION",
+ justification =
+ "Used for sending commands between authorized agent and server. Class filtering is done through JEP-200.")
+ static Command readFromObjectStream(Channel channel, ObjectInputStream ois)
+ throws IOException, ClassNotFoundException {
Channel old = Channel.setCurrent(channel);
try {
- return (Command)ois.readObject();
+ return (Command) ois.readObject();
} finally {
Channel.setCurrent(old);
}
@@ -177,8 +179,7 @@ static Command readFromObjectStream(Channel channel, ObjectInputStream ois) thro
private static final long serialVersionUID = 1L;
private final class Source extends Exception {
- public Source() {
- }
+ public Source() {}
private Source(@CheckForNull Throwable cause) {
super(cause);
diff --git a/src/main/java/hudson/remoting/CommandTransport.java b/src/main/java/hudson/remoting/CommandTransport.java
index 9116eb0b0..c38f126d0 100644
--- a/src/main/java/hudson/remoting/CommandTransport.java
+++ b/src/main/java/hudson/remoting/CommandTransport.java
@@ -8,11 +8,11 @@
/**
* Lower level abstraction under {@link Channel} for sending and receiving commands
- *
+ *
*
* {@link Channel} is internally implemented on top of a transport that satisfies
* the following characteristics:
- *
+ *
*
* Point-to-point
*
@@ -32,7 +32,7 @@
* or else both sides must raise an error, like TCP.
*
*
- *
+ *
*
* {@linkplain ClassicCommandTransport the default traditional implementation} implements
* this on top of a TCP-like bi-directional byte stream, but {@link Channel} can work with
@@ -51,8 +51,7 @@
*/
public abstract class CommandTransport {
- protected CommandTransport() {
- }
+ protected CommandTransport() {}
/**
* SPI implemented by {@link Channel} so that the transport can pass the received command
@@ -61,20 +60,20 @@ protected CommandTransport() {
protected interface CommandReceiver {
/**
* Notifies the channel that a new {@link Command} was received from the other side.
- *
+ *
*
* {@link Channel} performs all the error recovery of the error resulting from the command invocation.
* {@link Channel} implements this method in a non-reentrant fashion; a transport can invoke this method
* from different threads, but as the class javadoc states, the transport must
* guarantee in-order delivery of the commands, and that means you cannot call this method
* concurrently.
- *
+ *
* @param cmd
* The command received. This object must be read from the payload
* using {@link Command#readFrom(Channel, byte[])}.
*/
void handle(Command cmd);
-
+
/**
* Indicates that the transport has encountered a problem.
* This tells the channel that it shouldn't expect future invocation of {@link #handle(Command)},
@@ -93,26 +92,26 @@ protected interface CommandReceiver {
/**
* Starts the transport.
- *
+ *
* This method is called once and only once at the end of the initialization of {@link Channel},
* after the {@link #getRemoteCapability()} is invoked.
- *
+ *
* The first purpose of this method is to provide a reference back to {@link Channel}, and
* the second purpose of this method is to allow {@link CommandTransport} to message pumping,
* where it starts receiving commands from the other side and pass them onto {@link CommandReceiver}.
- *
+ *
* This abstraction enables asynchronous processing — for example you can have a single thread
* serving a large number of {@link Channel}s via NIO.
- *
+ *
* For subtypes that prefer synchronous operation, extend from {@link SynchronousCommandTransport}.
- *
+ *
*
* Closing the read pump: {@link Channel} implements
* {@code Channel.CloseCommand} its own "end of command stream" marker, and
* therefore under the orderly shutdown scenario, it doesn't rely on the transport to provide EOF-like
* marker. Instead, {@link Channel} will call your {@link #closeRead()} (from the same thread
* that invoked {@link CommandReceiver#handle(Command)}) to indicate that it is done with the reading.
- *
+ *
*
* If the transport encounters any error from the lower layer (say, the underlying TCP/IP socket
* encountered a REST), then call {@link CommandReceiver#terminate(IOException)} to initiate the abnormal
@@ -122,7 +121,7 @@ protected interface CommandReceiver {
/**
* Called by {@link Channel} to send one command to the other side.
- *
+ *
* {@link Channel} serializes the invocation of this method for ordering. That is,
* at any given point in time only one thread executes this method.
*
@@ -146,7 +145,7 @@ protected interface CommandReceiver {
/**
* Called to close the write side of the transport, allowing the underlying transport
* to be shut down.
- *
+ *
*
* If the {@link Channel} aborts the communication, this method may end up invoked
* asynchronously, concurrently, and multiple times. The implementation must protect
@@ -157,7 +156,7 @@ protected interface CommandReceiver {
/**
* Called to indicate that the no further input is expected and any resources
* associated with reading commands should be freed.
- *
+ *
* {@link Channel#isInClosed()} can be also used to test if the command reading
* should terminate.
*/
@@ -166,7 +165,7 @@ protected interface CommandReceiver {
/**
* Historical artifact left for backward compatibility, necessary only for retaining
* {@link Channel#getUnderlyingOutput()}.
- *
+ *
*
* Historically, {@link CommandTransport} abstraction is introduced much later than
* {@link Channel}. The implementation of the historical {@link Channel} was mostly
@@ -174,7 +173,7 @@ protected interface CommandReceiver {
* there was one method in Channel that assumed that there's the underlying {@link OutputStream}
* (that now belongs to the implementation details of {@link CommandTransport}),
* hence this method.
- *
+ *
*
* This method is package private, to prevent new {@link CommandTransport} from
* providing this feature.
diff --git a/src/main/java/hudson/remoting/DaemonThreadFactory.java b/src/main/java/hudson/remoting/DaemonThreadFactory.java
index bc716597a..08d2d29bf 100644
--- a/src/main/java/hudson/remoting/DaemonThreadFactory.java
+++ b/src/main/java/hudson/remoting/DaemonThreadFactory.java
@@ -15,7 +15,8 @@ public class DaemonThreadFactory implements ThreadFactory {
public Thread newThread(@NonNull Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
- thread.setUncaughtExceptionHandler((t, e) -> LOGGER.log(Level.SEVERE, e, () -> "Unhandled exception in thread " + t));
+ thread.setUncaughtExceptionHandler(
+ (t, e) -> LOGGER.log(Level.SEVERE, e, () -> "Unhandled exception in thread " + t));
return thread;
}
}
diff --git a/src/main/java/hudson/remoting/DelegatingCallable.java b/src/main/java/hudson/remoting/DelegatingCallable.java
index 43619cd96..e178ca6b7 100644
--- a/src/main/java/hudson/remoting/DelegatingCallable.java
+++ b/src/main/java/hudson/remoting/DelegatingCallable.java
@@ -1,18 +1,18 @@
/*
* The MIT License
- *
+ *
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -39,18 +39,18 @@
* In such a case, implement this interface, instead of plain {@link Callable} and
* return a classloader that can see all the classes.
*
- * In case of Jenkins, {@code PluginManager.uberClassLoader} is a good candidate.
+ * In case of Jenkins, {@code PluginManager.uberClassLoader} is a good candidate.
*
* @author Kohsuke Kawaguchi
*/
-public interface DelegatingCallable extends Callable {
-
+public interface DelegatingCallable extends Callable {
+
/**
* Returns the class loader to be used for the callable.
- *
+ *
* @return {@link ClassLoader} to be used.
* The value may be {@code null} if the classloader is not being propagated to the remote side.
- * If all classes in the call are primitives or {@code Void}, the value may be also {@code null}.
+ * If all classes in the call are primitives or {@code Void}, the value may be also {@code null}.
* In such cased the handling code should try other possible classloaders.
*/
@CheckForNull
diff --git a/src/main/java/hudson/remoting/DelegatingExecutorService.java b/src/main/java/hudson/remoting/DelegatingExecutorService.java
index 8f6188e8f..b256f229f 100644
--- a/src/main/java/hudson/remoting/DelegatingExecutorService.java
+++ b/src/main/java/hudson/remoting/DelegatingExecutorService.java
@@ -74,18 +74,22 @@ public List> invokeAll(@NonNull Collection extends Callable>
@Override
@NonNull
- public List> invokeAll(@NonNull Collection extends Callable> tasks, long timeout, @NonNull TimeUnit unit) throws InterruptedException {
+ public List> invokeAll(
+ @NonNull Collection extends Callable> tasks, long timeout, @NonNull TimeUnit unit)
+ throws InterruptedException {
return base.invokeAll(tasks, timeout, unit);
}
@Override
@NonNull
- public T invokeAny(@NonNull Collection extends Callable> tasks) throws InterruptedException, ExecutionException {
+ public T invokeAny(@NonNull Collection extends Callable> tasks)
+ throws InterruptedException, ExecutionException {
return base.invokeAny(tasks);
}
@Override
- public T invokeAny(@NonNull Collection extends Callable> tasks, long timeout, @NonNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+ public T invokeAny(@NonNull Collection extends Callable> tasks, long timeout, @NonNull TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
return base.invokeAny(tasks, timeout, unit);
}
diff --git a/src/main/java/hudson/remoting/DiagnosedStreamCorruptionException.java b/src/main/java/hudson/remoting/DiagnosedStreamCorruptionException.java
index eb174a12d..24156a854 100644
--- a/src/main/java/hudson/remoting/DiagnosedStreamCorruptionException.java
+++ b/src/main/java/hudson/remoting/DiagnosedStreamCorruptionException.java
@@ -20,8 +20,8 @@ public class DiagnosedStreamCorruptionException extends StreamCorruptedException
@NonNull
private final byte[] readAhead;
- DiagnosedStreamCorruptionException(Exception cause, Exception diagnoseFailure,
- @NonNull byte[] readBack, @NonNull byte[] readAhead) {
+ DiagnosedStreamCorruptionException(
+ Exception cause, Exception diagnoseFailure, @NonNull byte[] readBack, @NonNull byte[] readAhead) {
initCause(cause);
this.diagnoseFailure = diagnoseFailure;
this.readBack = readBack;
@@ -43,20 +43,22 @@ public byte[] getReadAhead() {
}
@Override
- @SuppressFBWarnings(value = "INFORMATION_EXPOSURE_THROUGH_AN_ERROR_MESSAGE", justification = "Used for diagnosing stream corruption between agent and server.")
+ @SuppressFBWarnings(
+ value = "INFORMATION_EXPOSURE_THROUGH_AN_ERROR_MESSAGE",
+ justification = "Used for diagnosing stream corruption between agent and server.")
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append(super.toString()).append("\n");
buf.append("Read back: ").append(HexDump.toHex(readBack)).append('\n');
buf.append("Read ahead: ").append(HexDump.toHex(readAhead));
- if (diagnoseFailure!=null) {
+ if (diagnoseFailure != null) {
StringWriter w = new StringWriter();
PrintWriter p = new PrintWriter(w);
diagnoseFailure.printStackTrace(p);
p.flush();
buf.append("\nDiagnosis problem:\n ");
- buf.append(w.toString().trim().replace("\n","\n "));
+ buf.append(w.toString().trim().replace("\n", "\n "));
}
return buf.toString();
}
diff --git a/src/main/java/hudson/remoting/DumbClassLoaderBridge.java b/src/main/java/hudson/remoting/DumbClassLoaderBridge.java
index 8ca68b77d..2e1944ab3 100644
--- a/src/main/java/hudson/remoting/DumbClassLoaderBridge.java
+++ b/src/main/java/hudson/remoting/DumbClassLoaderBridge.java
@@ -53,15 +53,20 @@ public byte[][] getResources(String name) throws IOException {
@Override
public Map fetch3(String className) throws ClassNotFoundException {
RemoteClassLoader.ClassFile cf = fetch2(className);
- return Map.of(className,
- new RemoteClassLoader.ClassFile2(cf.classLoader, new ResourceImageDirect(cf.classImage), null, null, null));
+ return Map.of(
+ className,
+ new RemoteClassLoader.ClassFile2(
+ cf.classLoader, new ResourceImageDirect(cf.classImage), null, null, null));
}
@Override
public RemoteClassLoader.ResourceFile getResource2(String name) throws IOException {
byte[] img = base.getResource(name);
- if (img==null) return null;
- return new RemoteClassLoader.ResourceFile(new ResourceImageDirect(img), null); // we are on the receiving side, so null is ok
+ if (img == null) {
+ return null;
+ }
+ return new RemoteClassLoader.ResourceFile(
+ new ResourceImageDirect(img), null); // we are on the receiving side, so null is ok
}
@Override
@@ -70,7 +75,8 @@ public RemoteClassLoader.ResourceFile[] getResources2(String name) throws IOExce
byte[][] r = base.getResources(name);
RemoteClassLoader.ResourceFile[] res = new RemoteClassLoader.ResourceFile[r.length];
for (int i = 0; i < res.length; i++) {
- res[i] = new RemoteClassLoader.ResourceFile(new ResourceImageDirect(r[i]), null); // we are on the receiving side, so null is ok
+ res[i] = new RemoteClassLoader.ResourceFile(
+ new ResourceImageDirect(r[i]), null); // we are on the receiving side, so null is ok
}
return res;
}
@@ -79,5 +85,4 @@ public RemoteClassLoader.ResourceFile[] getResources2(String name) throws IOExce
public String getName() throws IOException {
return base.getName();
}
-
}
diff --git a/src/main/java/hudson/remoting/Engine.java b/src/main/java/hudson/remoting/Engine.java
index 4af2efda2..78620b73c 100644
--- a/src/main/java/hudson/remoting/Engine.java
+++ b/src/main/java/hudson/remoting/Engine.java
@@ -1,18 +1,18 @@
/*
* The MIT License
- *
+ *
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -132,6 +132,7 @@ public class Engine extends Thread {
*/
private final ExecutorService executor = Executors.newCachedThreadPool(new ThreadFactory() {
private final ThreadFactory defaultFactory = Executors.defaultThreadFactory();
+
@Override
public Thread newThread(@NonNull final Runnable r) {
Thread thread = defaultFactory.newThread(() -> {
@@ -139,7 +140,8 @@ public Thread newThread(@NonNull final Runnable r) {
r.run();
});
thread.setDaemon(true);
- thread.setUncaughtExceptionHandler((t, e) -> LOGGER.log(Level.SEVERE, e, () -> "Uncaught exception in thread " + t));
+ thread.setUncaughtExceptionHandler(
+ (t, e) -> LOGGER.log(Level.SEVERE, e, () -> "Uncaught exception in thread " + t));
return thread;
}
});
@@ -174,6 +176,7 @@ public Thread newThread(@NonNull final Runnable r) {
*/
@CheckForNull
private URL hudsonUrl;
+
private final String secretKey;
private final String agentName;
private boolean webSocket;
@@ -205,7 +208,7 @@ public Thread newThread(@NonNull final Runnable r) {
* @since 2.62.1
*/
private boolean keepAlive = true;
-
+
@CheckForNull
private JarCache jarCache = null;
@@ -217,14 +220,14 @@ public Thread newThread(@NonNull final Runnable r) {
*/
@CheckForNull
private Path agentLog;
-
+
/**
* Specified location of the property file with JUL settings.
* @since 3.8
*/
@CheckForNull
private Path loggingConfigFilePath = null;
-
+
/**
* Specifies a default working directory of the remoting instance.
* If specified, this directory will be used to store logs, JAR cache, etc.
@@ -255,7 +258,8 @@ public Thread newThread(@NonNull final Runnable r) {
*/
public boolean failIfWorkDirIsMissing = WorkDirManager.DEFAULT_FAIL_IF_WORKDIR_IS_MISSING;
- private final DelegatingX509ExtendedTrustManager agentTrustManager = new DelegatingX509ExtendedTrustManager(new BlindTrustX509ExtendedTrustManager());
+ private final DelegatingX509ExtendedTrustManager agentTrustManager =
+ new DelegatingX509ExtendedTrustManager(new BlindTrustX509ExtendedTrustManager());
private final String directConnection;
private final String instanceIdentity;
@@ -265,17 +269,24 @@ public Engine(EngineListener listener, List hudsonUrls, String secretKey, S
this(listener, hudsonUrls, secretKey, agentName, null, null, null);
}
- public Engine(EngineListener listener, List hudsonUrls, String secretKey, String agentName, String directConnection, String instanceIdentity,
- Set protocols) {
+ public Engine(
+ EngineListener listener,
+ List hudsonUrls,
+ String secretKey,
+ String agentName,
+ String directConnection,
+ String instanceIdentity,
+ Set protocols) {
this.listener = listener;
this.directConnection = directConnection;
this.events.add(listener);
- this.candidateUrls = hudsonUrls.stream().map(Engine::ensureTrailingSlash).collect(Collectors.toList());
+ this.candidateUrls =
+ hudsonUrls.stream().map(Engine::ensureTrailingSlash).collect(Collectors.toList());
this.secretKey = secretKey;
this.agentName = agentName;
this.instanceIdentity = instanceIdentity;
this.protocols = protocols;
- if(candidateUrls.isEmpty() && instanceIdentity == null) {
+ if (candidateUrls.isEmpty() && instanceIdentity == null) {
throw new IllegalArgumentException("No URLs given");
}
setUncaughtExceptionHandler((t, e) -> {
@@ -305,7 +316,7 @@ private static URL ensureTrailingSlash(URL u) {
public synchronized void startEngine() throws IOException {
startEngine(false);
}
-
+
/**
* Starts engine.
* @param dryRun If {@code true}, do not actually start the engine.
@@ -314,7 +325,7 @@ public synchronized void startEngine() throws IOException {
/*package*/ void startEngine(boolean dryRun) throws IOException {
LOGGER.log(Level.INFO, "Using Remoting version: {0}", Launcher.VERSION);
@CheckForNull File jarCacheDirectory = null;
-
+
// Prepare the working directory if required
if (workDir != null) {
final WorkDirManager workDirManager = WorkDirManager.getInstance();
@@ -322,20 +333,23 @@ public synchronized void startEngine() throws IOException {
// Somebody has already specificed Jar Cache, hence we do not need it in the workspace.
workDirManager.disable(WorkDirManager.DirType.JAR_CACHE_DIR);
}
-
+
if (loggingConfigFilePath != null) {
workDirManager.setLoggingConfig(loggingConfigFilePath.toFile());
}
-
+
final Path path = workDirManager.initializeWorkDir(workDir.toFile(), internalDir, failIfWorkDirIsMissing);
jarCacheDirectory = workDirManager.getLocation(WorkDirManager.DirType.JAR_CACHE_DIR);
workDirManager.setupLogging(path, agentLog);
} else if (jarCache == null) {
- LOGGER.log(Level.WARNING, "No Working Directory. Using the legacy JAR Cache location: {0}", JarCache.DEFAULT_NOWS_JAR_CACHE_LOCATION);
+ LOGGER.log(
+ Level.WARNING,
+ "No Working Directory. Using the legacy JAR Cache location: {0}",
+ JarCache.DEFAULT_NOWS_JAR_CACHE_LOCATION);
jarCacheDirectory = JarCache.DEFAULT_NOWS_JAR_CACHE_LOCATION;
}
-
- if (jarCache == null){
+
+ if (jarCache == null) {
if (jarCacheDirectory == null) {
// Should never happen in the current code
throw new IOException("Cannot find the JAR Cache location");
@@ -349,7 +363,7 @@ public synchronized void startEngine() throws IOException {
} else {
LOGGER.log(Level.INFO, "Using custom JAR Cache: {0}", jarCache);
}
-
+
// Start the engine thread
if (!dryRun) {
this.start();
@@ -365,7 +379,7 @@ public synchronized void startEngine() throws IOException {
public void setJarCache(@NonNull JarCache jarCache) {
this.jarCache = jarCache;
}
-
+
/**
* Sets path to the property file with JUL settings.
* @param filePath JAR Cache to be used
@@ -481,7 +495,9 @@ public void setInternalDir(@NonNull String internalDir) {
* @param failIfWorkDirIsMissing Flag
* @since 3.8
*/
- public void setFailIfWorkDirIsMissing(boolean failIfWorkDirIsMissing) { this.failIfWorkDirIsMissing = failIfWorkDirIsMissing; }
+ public void setFailIfWorkDirIsMissing(boolean failIfWorkDirIsMissing) {
+ this.failIfWorkDirIsMissing = failIfWorkDirIsMissing;
+ }
/**
* Returns {@code true} if and only if the socket to the controller will have {@link Socket#setKeepAlive(boolean)} set.
@@ -502,9 +518,7 @@ public void setKeepAlive(boolean keepAlive) {
}
public void setCandidateCertificates(List candidateCertificates) {
- this.candidateCertificates = candidateCertificates == null
- ? null
- : new ArrayList<>(candidateCertificates);
+ this.candidateCertificates = candidateCertificates == null ? null : new ArrayList<>(candidateCertificates);
}
public void addCandidateCertificate(X509Certificate certificate) {
@@ -557,7 +571,8 @@ public void run() {
try {
kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
} catch (NoSuchAlgorithmException e) {
- throw new IllegalStateException("Java runtime specification requires support for default key manager", e);
+ throw new IllegalStateException(
+ "Java runtime specification requires support for default key manager", e);
}
try {
kmf.init(store, password);
@@ -565,7 +580,7 @@ public void run() {
throw new IllegalStateException(e);
}
try {
- context.init(kmf.getKeyManagers(), new TrustManager[]{agentTrustManager}, null);
+ context.init(kmf.getKeyManagers(), new TrustManager[] {agentTrustManager}, null);
} catch (KeyManagementException e) {
events.error(e);
return;
@@ -577,7 +592,9 @@ public void run() {
}
}
- @SuppressFBWarnings(value = {"REC_CATCH_EXCEPTION", "URLCONNECTION_SSRF_FD"}, justification = "checked exceptions were a mistake to begin with; connecting to Jenkins from agent")
+ @SuppressFBWarnings(
+ value = {"REC_CATCH_EXCEPTION", "URLCONNECTION_SSRF_FD"},
+ justification = "checked exceptions were a mistake to begin with; connecting to Jenkins from agent")
private void runWebSocket() {
try {
String localCap = new Capability().toASCII();
@@ -594,11 +611,13 @@ private void runWebSocket() {
AtomicReference ch = new AtomicReference<>();
class HeaderHandler extends ClientEndpointConfig.Configurator {
Capability remoteCapability = new Capability();
+
@Override
public void beforeRequest(Map> headers) {
headers.putAll(addedHeaders);
LOGGER.fine(() -> "Sending: " + headers);
}
+
@Override
public void afterResponse(HandshakeResponse hr) {
LOGGER.fine(() -> "Receiving: " + hr.getHeaders());
@@ -607,7 +626,8 @@ public void afterResponse(HandshakeResponse hr) {
VersionNumber minimumSupportedVersion = new VersionNumber(remotingMinimumVersion.get(0));
VersionNumber currentVersion = new VersionNumber(Launcher.VERSION);
if (currentVersion.isOlderThan(minimumSupportedVersion)) {
- events.error(new IOException("Agent version " + minimumSupportedVersion + " or newer is required."));
+ events.error(new IOException(
+ "Agent version " + minimumSupportedVersion + " or newer is required."));
}
}
try {
@@ -631,7 +651,9 @@ public void afterResponse(HandshakeResponse hr) {
}
HeaderHandler headerHandler = new HeaderHandler();
class AgentEndpoint extends Endpoint {
- @SuppressFBWarnings(value = "UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", justification = "just trust me here")
+ @SuppressFBWarnings(
+ value = "UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR",
+ justification = "just trust me here")
AgentEndpoint.Transport transport;
@Override
@@ -640,13 +662,15 @@ public void onOpen(Session session, EndpointConfig config) {
session.addMessageHandler(ByteBuffer.class, this::onMessage);
try {
transport = new Transport(session);
- ch.set(new ChannelBuilder(agentName, executor).
- withJarCacheOrDefault(jarCache). // unless EngineJnlpConnectionStateListener can be used for this purpose
- build(transport));
+ ch.set(new ChannelBuilder(agentName, executor)
+ .withJarCacheOrDefault(jarCache)
+ . // unless EngineJnlpConnectionStateListener can be used for this purpose
+ build(transport));
} catch (IOException x) {
events.error(x);
}
}
+
private void onMessage(ByteBuffer message) {
try {
transport.receive(message);
@@ -657,18 +681,24 @@ private void onMessage(ByteBuffer message) {
Thread.currentThread().interrupt();
}
}
+
@Override
- @SuppressFBWarnings(value = "RV_RETURN_VALUE_IGNORED_BAD_PRACTICE",
- justification = "We want the transport.terminate method to run asynchronously and don't want to wait for its status.")
+ @SuppressFBWarnings(
+ value = "RV_RETURN_VALUE_IGNORED_BAD_PRACTICE",
+ justification =
+ "We want the transport.terminate method to run asynchronously and don't want to wait for its status.")
public void onClose(Session session, CloseReason closeReason) {
LOGGER.fine(() -> "onClose: " + closeReason);
// making this call async to avoid potential deadlocks when some thread is holding a lock on the
// channel object while this thread is trying to acquire it to call Transport#terminate
ch.get().executor.submit(() -> transport.terminate(new ChannelClosedException(ch.get(), null)));
}
+
@Override
- @SuppressFBWarnings(value = "RV_RETURN_VALUE_IGNORED_BAD_PRACTICE",
- justification = "We want the transport.terminate method to run asynchronously and don't want to wait for its status.")
+ @SuppressFBWarnings(
+ value = "RV_RETURN_VALUE_IGNORED_BAD_PRACTICE",
+ justification =
+ "We want the transport.terminate method to run asynchronously and don't want to wait for its status.")
public void onError(Session session, Throwable x) {
// TODO or would events.error(x) be better?
LOGGER.log(Level.FINE, null, x);
@@ -678,15 +708,20 @@ public void onError(Session session, Throwable x) {
class Transport extends AbstractByteBufferCommandTransport {
final Session session;
+
Transport(Session session) {
super(true);
this.session = session;
}
+
@Override
protected void write(ByteBuffer headerAndData) throws IOException {
- LOGGER.finest(() -> "sending message of length " + (headerAndData.remaining() - ChunkHeader.SIZE));
+ LOGGER.finest(() ->
+ "sending message of length " + (headerAndData.remaining() - ChunkHeader.SIZE));
try {
- session.getAsyncRemote().sendBinary(headerAndData).get(5, TimeUnit.MINUTES);
+ session.getAsyncRemote()
+ .sendBinary(headerAndData)
+ .get(5, TimeUnit.MINUTES);
} catch (Exception x) {
throw new IOException(x);
}
@@ -696,11 +731,13 @@ protected void write(ByteBuffer headerAndData) throws IOException {
public Capability getRemoteCapability() {
return headerHandler.remoteCapability;
}
+
@Override
public void closeWrite() throws IOException {
events.status("Write side closed");
session.close();
}
+
@Override
public void closeRead() throws IOException {
events.status("Read side closed");
@@ -716,7 +753,9 @@ public void closeRead() throws IOException {
String proxyHost = System.getProperty("http.proxyHost", System.getenv("proxy_host"));
String proxyPort = System.getProperty("http.proxyPort");
- if (proxyHost != null && "http".equals(hudsonUrl.getProtocol()) && NoProxyEvaluator.shouldProxy(hudsonUrl.getHost())) {
+ if (proxyHost != null
+ && "http".equals(hudsonUrl.getProtocol())
+ && NoProxyEvaluator.shouldProxy(hudsonUrl.getHost())) {
URI proxyUri;
if (proxyPort != null) {
proxyUri = URI.create(String.format("http://%s:%s", proxyHost, proxyPort));
@@ -725,7 +764,15 @@ public void closeRead() throws IOException {
}
client.getProperties().put(ClientProperties.PROXY_URI, proxyUri);
if (proxyCredentials != null) {
- client.getProperties().put(ClientProperties.PROXY_HEADERS, Map.of("Proxy-Authorization", "Basic " + Base64.getEncoder().encodeToString(proxyCredentials.getBytes(StandardCharsets.UTF_8))));
+ client.getProperties()
+ .put(
+ ClientProperties.PROXY_HEADERS,
+ Map.of(
+ "Proxy-Authorization",
+ "Basic "
+ + Base64.getEncoder()
+ .encodeToString(proxyCredentials.getBytes(
+ StandardCharsets.UTF_8))));
}
}
@@ -738,8 +785,12 @@ public void closeRead() throws IOException {
client.getProperties().put(ClientProperties.SSL_ENGINE_CONFIGURATOR, sslEngineConfigurator);
}
}
- container.connectToServer(new AgentEndpoint(),
- ClientEndpointConfig.Builder.create().configurator(headerHandler).build(), URI.create(wsUrl + "wsagents/"));
+ container.connectToServer(
+ new AgentEndpoint(),
+ ClientEndpointConfig.Builder.create()
+ .configurator(headerHandler)
+ .build(),
+ URI.create(wsUrl + "wsagents/"));
while (ch.get() == null) {
Thread.sleep(100);
}
@@ -759,7 +810,8 @@ public void closeRead() throws IOException {
return;
}
TimeUnit.SECONDS.sleep(10);
- // Unlike JnlpAgentEndpointResolver, we do not use $jenkins/tcpSlaveAgentListener/, as that will be a 404 if the TCP port is disabled.
+ // Unlike JnlpAgentEndpointResolver, we do not use $jenkins/tcpSlaveAgentListener/, as that will be
+ // a 404 if the TCP port is disabled.
URL ping = new URL(hudsonUrl, "login");
try {
HttpURLConnection conn = (HttpURLConnection) ping.openConnection();
@@ -799,11 +851,11 @@ private void innerRun(IOHub hub, SSLContext context, ExecutorService service) {
.withSSLContext(context)
.withPreferNonBlockingIO(false) // we only have one connection, prefer blocking I/O
.handlers();
- final Map headers = new HashMap<>();
+ final Map headers = new HashMap<>();
headers.put(JnlpConnectionState.CLIENT_NAME_KEY, agentName);
headers.put(JnlpConnectionState.SECRET_KEY, secretKey);
List jenkinsUrls = new ArrayList<>();
- for (URL url: candidateUrls) {
+ for (URL url : candidateUrls) {
jenkinsUrls.add(url.toExternalForm());
}
JnlpEndpointResolver resolver = createEndpointResolver(jenkinsUrls, agentName);
@@ -811,12 +863,13 @@ private void innerRun(IOHub hub, SSLContext context, ExecutorService service) {
try {
boolean first = true;
firstAttempt = Instant.now();
- while(true) {
- if(first) {
+ while (true) {
+ if (first) {
first = false;
} else {
- if(noReconnect)
+ if (noReconnect) {
return; // exit
+ }
}
if (Util.shouldBailOut(firstAttempt, noReconnectAfter)) {
events.status("Bailing out after " + DurationFormatter.format(noReconnectAfter));
@@ -828,12 +881,15 @@ private void innerRun(IOHub hub, SSLContext context, ExecutorService service) {
endpoint = resolver.resolve();
} catch (IOException e) {
if (!noReconnect) {
- events.status("Could not locate server among " + candidateUrls + "; waiting 10 seconds before retry", e);
+ events.status(
+ "Could not locate server among " + candidateUrls + "; waiting 10 seconds before retry",
+ e);
// TODO refactor various sleep statements into a common method
TimeUnit.SECONDS.sleep(10);
continue;
} else {
- if (Boolean.getBoolean(Engine.class.getName() + ".nonFatalJnlpAgentEndpointResolutionExceptions")) {
+ if (Boolean.getBoolean(
+ Engine.class.getName() + ".nonFatalJnlpAgentEndpointResolutionExceptions")) {
events.status("Could not resolve JNLP agent endpoint", e);
} else {
events.error(e);
@@ -847,14 +903,12 @@ private void innerRun(IOHub hub, SSLContext context, ExecutorService service) {
}
hudsonUrl = endpoint.getServiceUrl();
- events.status(String.format("Agent discovery successful%n"
- + " Agent address: %s%n"
- + " Agent port: %d%n"
- + " Identity: %s",
- endpoint.getHost(),
- endpoint.getPort(),
- KeyUtils.fingerprint(endpoint.getPublicKey()))
- );
+ events.status(String.format(
+ "Agent discovery successful%n"
+ + " Agent address: %s%n"
+ + " Agent port: %d%n"
+ + " Identity: %s",
+ endpoint.getHost(), endpoint.getPort(), KeyUtils.fingerprint(endpoint.getPublicKey())));
PublicKeyMatchingX509ExtendedTrustManager delegate = new PublicKeyMatchingX509ExtendedTrustManager();
RSAPublicKey publicKey = endpoint.getPublicKey();
if (publicKey != null) {
@@ -886,14 +940,18 @@ private void innerRun(IOHub hub, SSLContext context, ExecutorService service) {
triedAtLeastOneProtocol = true;
events.status("Trying protocol: " + protocol.getName());
try {
- channel = protocol.connect(jnlpSocket, headers, new EngineJnlpConnectionStateListener(endpoint.getPublicKey(), headers)).get();
+ channel = protocol.connect(
+ jnlpSocket,
+ headers,
+ new EngineJnlpConnectionStateListener(endpoint.getPublicKey(), headers))
+ .get();
} catch (IOException ioe) {
events.status("Protocol " + protocol.getName() + " failed to establish channel", ioe);
} catch (RuntimeException e) {
events.status("Protocol " + protocol.getName() + " encountered a runtime error", e);
} catch (Error e) {
- events.status("Protocol " + protocol.getName() + " could not be completed due to an error",
- e);
+ events.status(
+ "Protocol " + protocol.getName() + " could not be completed due to an error", e);
} catch (Throwable e) {
events.status("Protocol " + protocol.getName() + " encountered an unexpected exception", e);
}
@@ -932,8 +990,9 @@ private void innerRun(IOHub hub, SSLContext context, ExecutorService service) {
}
}
}
- if(noReconnect)
+ if (noReconnect) {
return; // exit
+ }
firstAttempt = Instant.now();
events.onDisconnect();
@@ -956,16 +1015,25 @@ private JnlpEndpointResolver createEndpointResolver(List jenkinsUrls, St
} catch (Exception e) {
events.error(e);
}
- resolver = new JnlpAgentEndpointResolver(jenkinsUrls, agentName, credentials, proxyCredentials, tunnel,
- sslSocketFactory, disableHttpsCertValidation, noReconnectAfter);
+ resolver = new JnlpAgentEndpointResolver(
+ jenkinsUrls,
+ agentName,
+ credentials,
+ proxyCredentials,
+ tunnel,
+ sslSocketFactory,
+ disableHttpsCertValidation,
+ noReconnectAfter);
} else {
- resolver = new JnlpAgentEndpointConfigurator(directConnection, instanceIdentity, protocols, proxyCredentials);
+ resolver =
+ new JnlpAgentEndpointConfigurator(directConnection, instanceIdentity, protocols, proxyCredentials);
}
return resolver;
}
private void onConnectionRejected(String greeting) throws InterruptedException {
- events.status("reconnect rejected, sleeping 10s: ", new Exception("The server rejected the connection: " + greeting));
+ events.status(
+ "reconnect rejected, sleeping 10s: ", new Exception("The server rejected the connection: " + greeting));
// TODO refactor various sleep statements into a common method
TimeUnit.SECONDS.sleep(10);
}
@@ -980,18 +1048,19 @@ private Socket connectTcp(@NonNull JnlpAgentEndpoint endpoint) throws IOExceptio
String msg = "Connecting to " + endpoint.getHost() + ':' + endpoint.getPort();
events.status(msg);
int retry = 1;
- while(true) {
+ while (true) {
try {
- final Socket s = endpoint.open(SOCKET_TIMEOUT); // default is 30 mins. See PingThread for the ping interval
+ final Socket s =
+ endpoint.open(SOCKET_TIMEOUT); // default is 30 mins. See PingThread for the ping interval
s.setKeepAlive(keepAlive);
return s;
} catch (IOException e) {
- if(retry++>10) {
+ if (retry++ > 10) {
throw e;
}
// TODO refactor various sleep statements into a common method
TimeUnit.SECONDS.sleep(10);
- events.status(msg+" (retrying:"+retry+")",e);
+ events.status(msg + " (retrying:" + retry + ")", e);
}
}
}
@@ -1013,13 +1082,14 @@ public static Engine current() {
@SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", justification = "File path is loaded from system properties.")
static KeyStore getCacertsKeyStore()
throws PrivilegedActionException, KeyStoreException, NoSuchProviderException, CertificateException,
- NoSuchAlgorithmException, IOException {
- Map properties = AccessController.doPrivileged(
- (PrivilegedExceptionAction>) () -> {
+ NoSuchAlgorithmException, IOException {
+ Map properties =
+ AccessController.doPrivileged((PrivilegedExceptionAction>) () -> {
Map result = new HashMap<>();
result.put("trustStore", System.getProperty("javax.net.ssl.trustStore"));
result.put("javaHome", System.getProperty("java.home"));
- result.put("trustStoreType",
+ result.put(
+ "trustStoreType",
System.getProperty("javax.net.ssl.trustStoreType", KeyStore.getDefaultType()));
result.put("trustStoreProvider", System.getProperty("javax.net.ssl.trustStoreProvider", ""));
result.put("trustStorePasswd", System.getProperty("javax.net.ssl.trustStorePassword", ""));
@@ -1037,13 +1107,11 @@ static KeyStore getCacertsKeyStore()
trustStoreStream = getFileInputStream(trustStoreFile);
} else {
String javaHome = properties.get("javaHome");
- trustStoreFile = new File(
- javaHome + File.separator + "lib" + File.separator + "security" + File.separator
- + "jssecacerts");
+ trustStoreFile = new File(javaHome + File.separator + "lib" + File.separator + "security"
+ + File.separator + "jssecacerts");
if ((trustStoreStream = getFileInputStream(trustStoreFile)) == null) {
- trustStoreFile = new File(
- javaHome + File.separator + "lib" + File.separator + "security" + File.separator
- + "cacerts");
+ trustStoreFile = new File(javaHome + File.separator + "lib" + File.separator + "security"
+ + File.separator + "cacerts");
trustStoreStream = getFileInputStream(trustStoreFile);
}
}
@@ -1104,11 +1172,11 @@ private static FileInputStream getFileInputStream(final File file) throws Privil
@CheckForNull
private static SSLContext getSSLContext(List x509Certificates, boolean noCertificateCheck)
throws PrivilegedActionException, KeyStoreException, NoSuchProviderException, CertificateException,
- NoSuchAlgorithmException, IOException, KeyManagementException {
+ NoSuchAlgorithmException, IOException, KeyManagementException {
SSLContext sslContext = null;
if (noCertificateCheck) {
sslContext = SSLContext.getInstance("TLS");
- sslContext.init(null, new TrustManager[]{new NoCheckTrustManager()}, new SecureRandom());
+ sslContext.init(null, new TrustManager[] {new NoCheckTrustManager()}, new SecureRandom());
} else if (x509Certificates != null && !x509Certificates.isEmpty()) {
KeyStore keyStore = getCacertsKeyStore();
// load the keystore
@@ -1128,12 +1196,12 @@ private static SSLContext getSSLContext(List x509Certificates,
}
return sslContext;
}
-
+
@CheckForNull
@Restricted(NoExternalUse.class)
static SSLSocketFactory getSSLSocketFactory(List x509Certificates, boolean noCertificateCheck)
throws PrivilegedActionException, KeyStoreException, NoSuchProviderException, CertificateException,
- NoSuchAlgorithmException, IOException, KeyManagementException {
+ NoSuchAlgorithmException, IOException, KeyManagementException {
SSLContext sslContext = getSSLContext(x509Certificates, noCertificateCheck);
return sslContext != null ? sslContext.getSocketFactory() : null;
}
@@ -1143,7 +1211,7 @@ static SSLSocketFactory getSSLSocketFactory(List x509Certificat
* A {@link SocketInputStream#read()} call associated with underlying Socket will block for only this amount of time
* @since 2.4
*/
- static final int SOCKET_TIMEOUT = Integer.getInteger(Engine.class.getName()+".socketTimeout",30*60*1000);
+ static final int SOCKET_TIMEOUT = Integer.getInteger(Engine.class.getName() + ".socketTimeout", 30 * 60 * 1000);
/**
* Get the agent name associated with this Engine instance.
@@ -1183,11 +1251,9 @@ public void beforeProperties(@NonNull JnlpConnectionState event) {
if (event instanceof Jnlp4ConnectionState) {
X509Certificate certificate = ((Jnlp4ConnectionState) event).getCertificate();
if (certificate != null) {
- String fingerprint = KeyUtils
- .fingerprint(certificate.getPublicKey());
+ String fingerprint = KeyUtils.fingerprint(certificate.getPublicKey());
if (!KeyUtils.equals(publicKey, certificate.getPublicKey())) {
- event.reject(new ConnectionRefusalException(
- "Expecting identity " + fingerprint));
+ event.reject(new ConnectionRefusalException("Expecting identity " + fingerprint));
}
events.status("Remote identity confirmed: " + fingerprint);
}
diff --git a/src/main/java/hudson/remoting/EngineListener.java b/src/main/java/hudson/remoting/EngineListener.java
index 95da284cd..32fe34495 100644
--- a/src/main/java/hudson/remoting/EngineListener.java
+++ b/src/main/java/hudson/remoting/EngineListener.java
@@ -1,18 +1,18 @@
/*
* The MIT License
- *
+ *
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -50,7 +50,7 @@ public interface EngineListener {
void status(String msg, Throwable t);
/**
- * Fatal error that's non recoverable.
+ * Fatal error that's non recoverable.
*/
void error(Throwable t);
diff --git a/src/main/java/hudson/remoting/EngineListenerAdapter.java b/src/main/java/hudson/remoting/EngineListenerAdapter.java
index 1a220ea67..5d2468345 100644
--- a/src/main/java/hudson/remoting/EngineListenerAdapter.java
+++ b/src/main/java/hudson/remoting/EngineListenerAdapter.java
@@ -8,22 +8,17 @@
*/
public abstract class EngineListenerAdapter implements EngineListener {
@Override
- public void status(String msg) {
- }
+ public void status(String msg) {}
@Override
- public void status(String msg, Throwable t) {
- }
+ public void status(String msg, Throwable t) {}
@Override
- public void error(Throwable t) {
- }
+ public void error(Throwable t) {}
@Override
- public void onDisconnect() {
- }
+ public void onDisconnect() {}
@Override
- public void onReconnect() {
- }
+ public void onReconnect() {}
}
diff --git a/src/main/java/hudson/remoting/EngineListenerSplitter.java b/src/main/java/hudson/remoting/EngineListenerSplitter.java
index face303d3..7555cae90 100644
--- a/src/main/java/hudson/remoting/EngineListenerSplitter.java
+++ b/src/main/java/hudson/remoting/EngineListenerSplitter.java
@@ -30,7 +30,7 @@ public void status(String msg) {
@Override
public void status(String msg, Throwable t) {
for (EngineListener l : listeners) {
- l.status(msg,t);
+ l.status(msg, t);
}
}
diff --git a/src/main/java/hudson/remoting/ExportTable.java b/src/main/java/hudson/remoting/ExportTable.java
index afa9629ee..34a117e42 100644
--- a/src/main/java/hudson/remoting/ExportTable.java
+++ b/src/main/java/hudson/remoting/ExportTable.java
@@ -47,8 +47,8 @@
* @author Kohsuke Kawaguchi
*/
final class ExportTable {
- private final Map> table = new HashMap<>();
- private final Map> reverse = new HashMap<>();
+ private final Map> table = new HashMap<>();
+ private final Map> reverse = new HashMap<>();
/**
* {@link ExportList}s which are actively recording the current
* export operation.
@@ -100,8 +100,8 @@ private final class Entry {
this.objectType = object.getClass().getName();
this.allocationTrace = EXPORT_TRACES ? new CreatedAt() : null;
- table.put(id,this);
- reverse.put(object,this);
+ table.put(id, this);
+ reverse.put(object, this);
}
void addRef() {
@@ -126,8 +126,9 @@ void pin() {
// addRef -> 0x80000000 => BOOM
// By making the decision point half way, we give the maximum number of releases away from the pinned
// magic value
- if (referenceCount<0x20000000)
+ if (referenceCount < 0x20000000) {
referenceCount += 0x40000000;
+ }
}
/**
@@ -137,7 +138,7 @@ void pin() {
* in case it was requested from the other side of the channel.
*/
void release(@CheckForNull Throwable callSite) {
- if(--referenceCount==0) {
+ if (--referenceCount == 0) {
table.remove(id);
reverse.remove(object);
@@ -146,15 +147,16 @@ void release(@CheckForNull Throwable callSite) {
releaseTrace = new ReleasedAt(callSite);
}
unexportLog.add(this);
- while (unexportLog.size() > UNEXPORT_LOG_SIZE)
+ while (unexportLog.size() > UNEXPORT_LOG_SIZE) {
unexportLog.remove(0);
+ }
}
}
private String interfaceNames() {
StringBuilder buf = new StringBuilder(10 + getInterfaces().length * 128);
String sep = "[";
- for (Class super T> clazz: getInterfaces()) {
+ for (Class super T> clazz : getInterfaces()) {
buf.append(sep).append(clazz.getName());
sep = ", ";
}
@@ -166,7 +168,9 @@ private String interfaceNames() {
* Dumps the contents of the entry.
*/
void dump(PrintWriter w) throws IOException {
- w.printf("#%d (ref.%d) : object=%s type=%s interfaces=%s%n", id, referenceCount, object, objectType, interfaceNames());
+ w.printf(
+ "#%d (ref.%d) : object=%s type=%s interfaces=%s%n",
+ id, referenceCount, object, objectType, interfaceNames());
if (allocationTrace != null) {
allocationTrace.printStackTrace(w);
}
@@ -180,7 +184,7 @@ String dump() {
try (PrintWriter pw = new PrintWriter(sw)) {
dump(pw);
} catch (IOException e) {
- throw new Error(e); // impossible
+ throw new Error(e); // impossible
}
return sw.toString();
}
@@ -190,15 +194,16 @@ synchronized Class super T>[] getInterfaces() {
}
synchronized void addInterface(Class super T> clazz) {
- for (Class super T> c: interfaces) {
- if (c.equals(clazz)) return;
+ for (Class super T> c : interfaces) {
+ if (c.equals(clazz)) {
+ return;
+ }
}
- Class super T>[] replacement = new Class[interfaces.length+1];
+ Class super T>[] replacement = new Class[interfaces.length + 1];
System.arraycopy(interfaces, 0, replacement, 0, interfaces.length);
replacement[interfaces.length] = clazz;
interfaces = replacement;
}
-
}
static class Source extends Exception {
@@ -212,7 +217,6 @@ static class Source extends Exception {
Source(@CheckForNull Throwable callSite) {
super(callSite);
}
-
}
static class CreatedAt extends Source {
@@ -222,7 +226,7 @@ static class CreatedAt extends Source {
@Override
public String toString() {
- return " Created at "+new Date(timestamp);
+ return " Created at " + new Date(timestamp);
}
}
@@ -233,7 +237,7 @@ static class ReleasedAt extends Source {
@Override
public String toString() {
- return " Released at "+new Date(timestamp);
+ return " Released at " + new Date(timestamp);
}
}
@@ -244,26 +248,32 @@ public String toString() {
* The class is not serializable.
*/
@Restricted(NoExternalUse.class)
- @SuppressFBWarnings(value = {"EQ_DOESNT_OVERRIDE_EQUALS", "SE_BAD_FIELD_INNER_CLASS"},
+ @SuppressFBWarnings(
+ value = {"EQ_DOESNT_OVERRIDE_EQUALS", "SE_BAD_FIELD_INNER_CLASS"},
justification = "ExportList is supposed to be serializable as ArrayList, but it is not. "
- + "The issue is ignored since the class does not belong to the public API")
+ + "The issue is ignored since the class does not belong to the public API")
public final class ExportList extends ArrayList> {
private final ExportList old;
+
private ExportList() {
- old=lists.get();
+ old = lists.get();
lists.set(this);
}
+
void release(Throwable callSite) {
- synchronized(ExportTable.this) {
- for (Entry> e : this)
+ synchronized (ExportTable.this) {
+ for (Entry> e : this) {
e.release(callSite);
+ }
}
}
+
void stopRecording() {
lists.set(old);
}
- private static final long serialVersionUID = 1L; // we don't actually serialize this class but just to shutup FindBugs
+ private static final long serialVersionUID =
+ 1L; // we don't actually serialize this class but just to shutup FindBugs
}
/**
@@ -284,7 +294,7 @@ ExportList startRecording() {
}
boolean isRecording() {
- return lists.get()!=null;
+ return lists.get() != null;
}
/**
@@ -302,7 +312,7 @@ boolean isRecording() {
* @param t Class instance
*/
synchronized int export(@NonNull Class clazz, @CheckForNull T t) {
- return export(clazz, t,true);
+ return export(clazz, t, true);
}
/**
@@ -317,7 +327,9 @@ synchronized int export(@NonNull Class clazz, @CheckForNull T t) {
* {@code 0} if the input parameter is {@code null}.
*/
synchronized int export(@NonNull Class clazz, @CheckForNull T t, boolean notifyListener) {
- if(t==null) return 0; // bootstrap classloader
+ if (t == null) {
+ return 0; // bootstrap classloader
+ }
Entry e = (Entry) reverse.get(t);
if (e == null) {
@@ -327,9 +339,11 @@ synchronized int export(@NonNull Class clazz, @CheckForNull T t, boolean
}
e.addRef();
- if(notifyListener) {
+ if (notifyListener) {
ExportList l = lists.get();
- if(l!=null) l.add(e);
+ if (l != null) {
+ l.add(e);
+ }
}
return e.id;
@@ -337,8 +351,9 @@ synchronized int export(@NonNull Class clazz, @CheckForNull T t, boolean
/*package*/ synchronized void pin(@NonNull Object t) {
Entry> e = reverse.get(t);
- if(e!=null)
+ if (e != null) {
e.pin();
+ }
}
/**
@@ -351,7 +366,9 @@ synchronized int export(@NonNull Class clazz, @CheckForNull T t, boolean
@NonNull
synchronized Object get(int id) throws ExecutionException {
Entry> e = table.get(id);
- if(e!=null) return e.object;
+ if (e != null) {
+ return e.object;
+ }
throw diagnoseInvalidObjectId(id);
}
@@ -364,7 +381,9 @@ synchronized Object get(int id) throws ExecutionException {
@CheckForNull
synchronized Object getOrNull(int oid) {
Entry> e = table.get(oid);
- if(e!=null) return e.object;
+ if (e != null) {
+ return e.object;
+ }
return null;
}
@@ -372,7 +391,9 @@ synchronized Object getOrNull(int oid) {
@NonNull
synchronized Class>[] type(int id) throws ExecutionException {
Entry> e = table.get(id);
- if(e!=null) return e.getInterfaces();
+ if (e != null) {
+ return e.getInterfaces();
+ }
throw diagnoseInvalidObjectId(id);
}
@@ -396,9 +417,9 @@ void abort(@CheckForNull Throwable e) {
for (Entry> v : values) {
if (v.object instanceof ErrorPropagatingOutputStream) {
try {
- ((ErrorPropagatingOutputStream)v.object).error(e);
+ ((ErrorPropagatingOutputStream) v.object).error(e);
} catch (Throwable x) {
- LOGGER.log(Level.INFO, "Failed to propagate a channel termination error",x);
+ LOGGER.log(Level.INFO, "Failed to propagate a channel termination error", x);
}
}
}
@@ -419,24 +440,25 @@ void abort(@CheckForNull Throwable e) {
*/
@NonNull
private synchronized ExecutionException diagnoseInvalidObjectId(int id) {
- Exception cause=null;
+ Exception cause = null;
if (!unexportLog.isEmpty()) {
for (Entry> e : unexportLog) {
- if (e.id==id) {
+ if (e.id == id) {
cause = new Exception("Object was recently deallocated\n" + Util.indent(e.dump()), e.releaseTrace);
break;
}
}
- if (cause==null) {
- // If there is no cause available, create an artificial cause and use the last unexport entry as an estimated release time if possible
+ if (cause == null) {
+ // If there is no cause available, create an artificial cause and use the last unexport entry as an
+ // estimated release time if possible
final ReleasedAt releasedAt = unexportLog.get(0).releaseTrace;
final Date releasedBefore = releasedAt != null ? new Date(releasedAt.timestamp) : new Date();
- cause = new Exception("Object appears to be deallocated at lease before "+ releasedBefore);
+ cause = new Exception("Object appears to be deallocated at lease before " + releasedBefore);
}
}
- return new ExecutionException("Invalid object ID "+id+" iota="+iota, cause);
+ return new ExecutionException("Invalid object ID " + id + " iota=" + iota, cause);
}
/**
@@ -454,14 +476,21 @@ void unexportByOid(Integer oid) {
* @param severeErrorIfMissing Consider missing object as {@link Level#SEVERE} error. {@link Level#FINE} otherwise
* @since 2.62
*/
- synchronized void unexportByOid(@CheckForNull Integer oid, @CheckForNull Throwable callSite, boolean severeErrorIfMissing) {
- if(oid==null) return;
+ synchronized void unexportByOid(
+ @CheckForNull Integer oid, @CheckForNull Throwable callSite, boolean severeErrorIfMissing) {
+ if (oid == null) {
+ return;
+ }
Entry> e = table.get(oid);
- if(e==null) {
+ if (e == null) {
Level loggingLevel = severeErrorIfMissing ? Level.SEVERE : Level.FINE;
- LOGGER.log(loggingLevel, "Trying to unexport an object that's already unexported", diagnoseInvalidObjectId(oid));
- if (callSite!=null)
+ LOGGER.log(
+ loggingLevel,
+ "Trying to unexport an object that's already unexported",
+ diagnoseInvalidObjectId(oid));
+ if (callSite != null) {
LOGGER.log(loggingLevel, "2nd unexport attempt is here", callSite);
+ }
return;
}
e.release(callSite);
@@ -477,7 +506,7 @@ synchronized void dump(@NonNull PrintWriter w) throws IOException {
}
}
- /*package*/ synchronized boolean isExported(Object o) {
+ /*package*/ synchronized boolean isExported(Object o) {
return reverse.containsKey(o);
}
@@ -485,7 +514,7 @@ synchronized void dump(@NonNull PrintWriter w) throws IOException {
* Defines number of entries to be stored in the unexport history.
* @since 2.40
*/
- public static int UNEXPORT_LOG_SIZE = Integer.getInteger(ExportTable.class.getName()+".unexportLogSize",1024);
+ public static int UNEXPORT_LOG_SIZE = Integer.getInteger(ExportTable.class.getName() + ".unexportLogSize", 1024);
static boolean EXPORT_TRACES = Boolean.getBoolean(ExportTable.class.getName() + ".exportTraces");
diff --git a/src/main/java/hudson/remoting/FastPipedInputStream.java b/src/main/java/hudson/remoting/FastPipedInputStream.java
index d764104c7..d36de2b33 100644
--- a/src/main/java/hudson/remoting/FastPipedInputStream.java
+++ b/src/main/java/hudson/remoting/FastPipedInputStream.java
@@ -44,6 +44,7 @@ public class FastPipedInputStream extends InputStream {
* Once closed, this is set to the stack trace of who closed it.
*/
ClosedBy closed = null;
+
int readLaps = 0;
int readPosition = 0;
WeakReference source;
@@ -51,7 +52,7 @@ public class FastPipedInputStream extends InputStream {
int writePosition = 0;
private final Throwable allocatedAt = new Throwable();
-
+
/**
* Creates an unconnected PipedInputStream with a default buffer size.
*/
@@ -74,7 +75,7 @@ public FastPipedInputStream(FastPipedOutputStream source) throws IOException {
* @exception IOException It was already connected.
*/
public FastPipedInputStream(FastPipedOutputStream source, int bufferSize) throws IOException {
- if(source != null) {
+ if (source != null) {
connect(source);
}
this.buffer = new byte[bufferSize];
@@ -82,7 +83,9 @@ public FastPipedInputStream(FastPipedOutputStream source, int bufferSize) throws
private void checkSource() throws IOException {
FastPipedOutputStream s = source.get();
- if (s==null) throw new IOException("Writer side has already been abandoned", allocatedAt);
+ if (s == null) {
+ throw new IOException("Writer side has already been abandoned", allocatedAt);
+ }
}
@Override
@@ -91,10 +94,10 @@ public int available() throws IOException {
* are located.
*/
synchronized (buffer) {
- return writePosition > readPosition /* The writer is in the same lap. */? writePosition
- - readPosition
- : (writePosition < readPosition /* The writer is in the next lap. */? buffer.length
- - readPosition + 1 + writePosition
+ return writePosition > readPosition /* The writer is in the same lap. */
+ ? writePosition - readPosition
+ : (writePosition < readPosition /* The writer is in the next lap. */
+ ? buffer.length - readPosition + 1 + writePosition
:
/* The writer is at the same position or a complete lap ahead. */
(writeLaps > readLaps ? buffer.length : 0));
@@ -106,10 +109,10 @@ public int available() throws IOException {
*/
@Override
public void close() throws IOException {
- if(source == null) {
+ if (source == null) {
throw new IOException("Unconnected pipe");
}
- synchronized(buffer) {
+ synchronized (buffer) {
closed = new ClosedBy(null);
// Release any pending writers.
buffer.notifyAll();
@@ -120,7 +123,7 @@ public void close() throws IOException {
* @exception IOException The pipe is already connected.
*/
public void connect(FastPipedOutputStream source) throws IOException {
- if(this.source != null) {
+ if (this.source != null) {
throw new IOException("Pipe already connected");
}
this.source = new WeakReference<>(source);
@@ -134,8 +137,7 @@ protected void finalize() throws Throwable {
}
@Override
- public void mark(int readLimit) {
- }
+ public void mark(int readLimit) {}
@Override
public boolean markSupported() {
@@ -158,16 +160,18 @@ public int read(@NonNull byte[] b) throws IOException {
*/
@Override
public int read(@NonNull byte[] b, int off, int len) throws IOException {
- if(source == null) {
+ if (source == null) {
throw new IOException("Unconnected pipe");
}
while (true) {
- synchronized(buffer) {
- if(writePosition == readPosition && writeLaps == readLaps) {
- if(closed!=null) {
+ synchronized (buffer) {
+ if (writePosition == readPosition && writeLaps == readLaps) {
+ if (closed != null) {
Throwable c = closed.getCause();
- if (c==null) return -1; // EOF
+ if (c == null) {
+ return -1; // EOF
+ }
throw new IOException(c);
}
checkSource(); // make sure the sink is still trying to read, or else fail the write.
@@ -185,13 +189,12 @@ public int read(@NonNull byte[] b, int off, int len) throws IOException {
// Don't read more than the capacity indicated by len or what's available
// in the circular buffer.
- int amount = Math.min(len, (writePosition > readPosition ? writePosition
- : buffer.length)
- - readPosition);
+ int amount =
+ Math.min(len, (writePosition > readPosition ? writePosition : buffer.length) - readPosition);
System.arraycopy(buffer, readPosition, b, off, amount);
readPosition += amount;
- if(readPosition == buffer.length) {// A lap was completed, so go back.
+ if (readPosition == buffer.length) { // A lap was completed, so go back.
readPosition = 0;
++readLaps;
}
diff --git a/src/main/java/hudson/remoting/FastPipedOutputStream.java b/src/main/java/hudson/remoting/FastPipedOutputStream.java
index 824e16405..9c9150182 100644
--- a/src/main/java/hudson/remoting/FastPipedOutputStream.java
+++ b/src/main/java/hudson/remoting/FastPipedOutputStream.java
@@ -74,7 +74,9 @@ public FastPipedOutputStream(FastPipedInputStream sink, int bufferSize) throws I
private FastPipedInputStream sink() throws IOException {
FastPipedInputStream s = sink.get();
- if (s==null) throw new IOException("Reader side has already been abandoned", allocatedAt);
+ if (s == null) {
+ throw new IOException("Reader side has already been abandoned", allocatedAt);
+ }
return s;
}
@@ -88,12 +90,12 @@ public void close() throws IOException {
@Override
public void error(Throwable e) throws IOException {
- if(sink == null) {
+ if (sink == null) {
throw new IOException("Unconnected pipe");
}
FastPipedInputStream s = sink();
- synchronized(s.buffer) {
- if (s.closed==null) {
+ synchronized (s.buffer) {
+ if (s.closed == null) {
s.closed = new FastPipedInputStream.ClosedBy(e);
flush();
}
@@ -104,7 +106,7 @@ public void error(Throwable e) throws IOException {
* @exception IOException The pipe is already connected.
*/
public void connect(FastPipedInputStream sink) throws IOException {
- if(this.sink != null) {
+ if (this.sink != null) {
throw new IOException("Pipe already connected");
}
this.sink = new WeakReference<>(sink);
@@ -120,7 +122,7 @@ protected void finalize() throws Throwable {
@Override
public void flush() throws IOException {
FastPipedInputStream s = sink();
- synchronized(s.buffer) {
+ synchronized (s.buffer) {
// Release all readers.
s.buffer.notifyAll();
}
@@ -128,7 +130,7 @@ public void flush() throws IOException {
@Override
public void write(int b) throws IOException {
- write(new byte[] { (byte) b });
+ write(new byte[] {(byte) b});
}
@Override
@@ -141,19 +143,19 @@ public void write(@NonNull byte[] b) throws IOException {
*/
@Override
public void write(@NonNull byte[] b, int off, int len) throws IOException {
- if(sink == null) {
+ if (sink == null) {
throw new IOException("Unconnected pipe");
}
- while (len>0) {
+ while (len > 0) {
FastPipedInputStream s = sink(); // make sure the sink is still trying to read, or else fail the write.
- if(s.closed!=null) {
+ if (s.closed != null) {
throw new IOException("Pipe is already closed", s.closed);
}
- synchronized(s.buffer) {
- if(s.writePosition == s.readPosition && s.writeLaps > s.readLaps) {
+ synchronized (s.buffer) {
+ if (s.writePosition == s.readPosition && s.writeLaps > s.readLaps) {
// The circular buffer is full, so wait for some reader to consume
// something.
@@ -163,11 +165,11 @@ public void write(@NonNull byte[] b, int off, int len) throws IOException {
Thread t = Thread.currentThread();
String oldName = t.getName();
- t.setName("Blocking to write "+HexDump.toHex(b,off,Math.min(len,256))+": "+oldName);
+ t.setName("Blocking to write " + HexDump.toHex(b, off, Math.min(len, 256)) + ": " + oldName);
try {
buf.wait(TIMEOUT);
} catch (InterruptedException e) {
- throw (InterruptedIOException)new InterruptedIOException(e.getMessage()).initCause(e);
+ throw (InterruptedIOException) new InterruptedIOException(e.getMessage()).initCause(e);
} finally {
t.setName(oldName);
}
@@ -177,13 +179,12 @@ public void write(@NonNull byte[] b, int off, int len) throws IOException {
// Don't write more than the capacity indicated by len or the space
// available in the circular buffer.
- int amount = Math.min(len, (s.writePosition < s.readPosition ? s.readPosition
- : s.buffer.length)
- - s.writePosition);
+ int amount = Math.min(
+ len, (s.writePosition < s.readPosition ? s.readPosition : s.buffer.length) - s.writePosition);
System.arraycopy(b, off, s.buffer, s.writePosition, amount);
s.writePosition += amount;
- if(s.writePosition == s.buffer.length) {
+ if (s.writePosition == s.buffer.length) {
s.writePosition = 0;
++s.writeLaps;
}
@@ -196,5 +197,5 @@ public void write(@NonNull byte[] b, int off, int len) throws IOException {
}
}
- static final int TIMEOUT = Integer.getInteger(FastPipedOutputStream.class.getName()+".timeout",10*1000);
+ static final int TIMEOUT = Integer.getInteger(FastPipedOutputStream.class.getName() + ".timeout", 10 * 1000);
}
diff --git a/src/main/java/hudson/remoting/FileSystemJarCache.java b/src/main/java/hudson/remoting/FileSystemJarCache.java
index 3b28be306..2d733081f 100644
--- a/src/main/java/hudson/remoting/FileSystemJarCache.java
+++ b/src/main/java/hudson/remoting/FileSystemJarCache.java
@@ -40,9 +40,9 @@ public class FileSystemJarCache extends JarCacheSupport {
@GuardedBy("itself")
private final Map checksumsByPath = new HashMap<>();
- //TODO: Create new IOException constructor
+ // TODO: Create new IOException constructor
/**
- * @param rootDir
+ * @param rootDir
* Root directory.
* @param touch
* True to touch the cached jar file that's used. This enables external LRU based cache
@@ -53,8 +53,9 @@ public class FileSystemJarCache extends JarCacheSupport {
public FileSystemJarCache(@NonNull File rootDir, boolean touch) {
this.rootDir = rootDir;
this.touch = touch;
- if (rootDir==null)
+ if (rootDir == null) {
throw new IllegalArgumentException("Root directory is null");
+ }
try {
Files.createDirectories(rootDir.toPath());
@@ -67,17 +68,17 @@ public FileSystemJarCache(@NonNull File rootDir, boolean touch) {
public String toString() {
return String.format("FileSystem JAR Cache: path=%s, touch=%s", rootDir, touch);
}
-
+
@Override
protected URL lookInCache(Channel channel, long sum1, long sum2) throws IOException, InterruptedException {
File jar = map(sum1, sum2);
if (jar.exists()) {
- LOGGER.log(Level.FINER, () -> String.format("Jar file cache hit %16X%16X",sum1,sum2));
- if (touch) {
+ LOGGER.log(Level.FINER, () -> String.format("Jar file cache hit %16X%16X", sum1, sum2));
+ if (touch) {
Files.setLastModifiedTime(PathUtils.fileToPath(jar), FileTime.fromMillis(System.currentTimeMillis()));
}
- if (notified.add(new Checksum(sum1,sum2))) {
- getJarLoader(channel).notifyJarPresence(sum1,sum2);
+ if (notified.add(new Checksum(sum1, sum2))) {
+ getJarLoader(channel).notifyJarPresence(sum1, sum2);
}
return jar.toURI().toURL();
}
@@ -85,7 +86,9 @@ protected URL lookInCache(Channel channel, long sum1, long sum2) throws IOExcept
}
@Override
- @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", justification = "The file path is a generated value based on server supplied data.")
+ @SuppressFBWarnings(
+ value = "PATH_TRAVERSAL_IN",
+ justification = "The file path is a generated value based on server supplied data.")
protected URL retrieve(Channel channel, long sum1, long sum2) throws IOException, InterruptedException {
Checksum expected = new Checksum(sum1, sum2);
File target = map(sum1, sum2);
@@ -99,8 +102,7 @@ protected URL retrieve(Channel channel, long sum1, long sum2) throws IOException
LOGGER.warning(String.format(
"Cached file checksum mismatch: %s%nExpected: %s%n Actual: %s",
- target.getAbsolutePath(), expected, actual
- ));
+ target.getAbsolutePath(), expected, actual));
Files.delete(PathUtils.fileToPath(target));
synchronized (checksumsByPath) {
checksumsByPath.remove(target.getCanonicalPath());
@@ -145,7 +147,7 @@ protected URL retrieve(Channel channel, long sum1, long sum2) throws IOException
Files.deleteIfExists(PathUtils.fileToPath(tmp));
}
} catch (IOException e) {
- throw new IOException("Failed to write to "+target, e);
+ throw new IOException("Failed to write to " + target, e);
}
}
@@ -160,7 +162,9 @@ private Checksum fileChecksum(File file) throws IOException {
// until calculated to be picked up from cache right away.
synchronized (checksumsByPath) {
Checksum checksum = checksumsByPath.get(location);
- if (checksum != null) return checksum;
+ if (checksum != null) {
+ return checksum;
+ }
checksum = Checksum.forFile(file);
checksumsByPath.put(location, checksum);
@@ -168,7 +172,9 @@ private Checksum fileChecksum(File file) throws IOException {
}
}
- @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", justification = "This path exists within a temp directory so the potential traversal is limited.")
+ @SuppressFBWarnings(
+ value = "PATH_TRAVERSAL_IN",
+ justification = "This path exists within a temp directory so the potential traversal is limited.")
/*package for testing*/ File createTempJar(@NonNull File target) throws IOException {
File parent = target.getParentFile();
Files.createDirectories(parent.toPath());
@@ -179,9 +185,9 @@ private Checksum fileChecksum(File file) throws IOException {
* Map to the cache jar file name.
*/
File map(long sum1, long sum2) {
- return new File(rootDir,String.format("%02X/%014X%016X.jar",
- (int)(sum1>>>(64-8)),
- sum1&0x00FFFFFFFFFFFFFFL, sum2));
+ return new File(
+ rootDir,
+ String.format("%02X/%014X%016X.jar", (int) (sum1 >>> (64 - 8)), sum1 & 0x00FFFFFFFFFFFFFFL, sum2));
}
private static final Logger LOGGER = Logger.getLogger(FileSystemJarCache.class.getName());
diff --git a/src/main/java/hudson/remoting/FlightRecorderInputStream.java b/src/main/java/hudson/remoting/FlightRecorderInputStream.java
index 845ae848b..9e2dcaa3f 100644
--- a/src/main/java/hudson/remoting/FlightRecorderInputStream.java
+++ b/src/main/java/hudson/remoting/FlightRecorderInputStream.java
@@ -22,7 +22,8 @@ class FlightRecorderInputStream extends InputStream {
* Size (in bytes) of the flight recorder ring buffer used for debugging remoting issues.
* @since 2.41
*/
- static final int BUFFER_SIZE = Integer.getInteger("hudson.remoting.FlightRecorderInputStream.BUFFER_SIZE", 1024 * 1024);
+ static final int BUFFER_SIZE =
+ Integer.getInteger("hudson.remoting.FlightRecorderInputStream.BUFFER_SIZE", 1024 * 1024);
private final InputStream source;
private ByteArrayRingBuffer recorder = new ByteArrayRingBuffer(BUFFER_SIZE);
@@ -53,13 +54,14 @@ public DiagnosedStreamCorruptionException analyzeCrash(Exception problem, String
final ByteArrayOutputStream readAhead = new ByteArrayOutputStream();
final IOException[] error = new IOException[1];
- Thread diagnosisThread = new Thread(diagnosisName+" stream corruption diagnosis thread") {
+ Thread diagnosisThread = new Thread(diagnosisName + " stream corruption diagnosis thread") {
@Override
public void run() {
int b;
try {
- // not all InputStream will look for the thread interrupt flag, so check that explicitly to be defensive
- while (!Thread.interrupted() && (b=source.read())!=-1) {
+ // not all InputStream will look for the thread interrupt flag, so check that explicitly to be
+ // defensive
+ while (!Thread.interrupted() && (b = source.read()) != -1) {
readAhead.write(b);
}
} catch (IOException e) {
@@ -81,26 +83,28 @@ public void run() {
}
IOException diagnosisProblem = error[0]; // capture the error, if any, before we kill the thread
- if (diagnosisThread.isAlive())
- diagnosisThread.interrupt(); // if it's not dead, kill
-
- return new DiagnosedStreamCorruptionException(problem,diagnosisProblem,getRecord(),readAhead.toByteArray());
+ if (diagnosisThread.isAlive()) {
+ diagnosisThread.interrupt(); // if it's not dead, kill
+ }
+ return new DiagnosedStreamCorruptionException(problem, diagnosisProblem, getRecord(), readAhead.toByteArray());
}
@Override
public int read() throws IOException {
int i = source.read();
- if (i>=0)
+ if (i >= 0) {
recorder.write(i);
+ }
return i;
}
@Override
public int read(@NonNull byte[] b, int off, int len) throws IOException {
len = source.read(b, off, len);
- if (len>0)
- recorder.write(b,off,len);
+ if (len > 0) {
+ recorder.write(b, off, len);
+ }
return len;
}
@@ -109,8 +113,8 @@ public int read(@NonNull byte[] b, int off, int len) throws IOException {
*/
@Override
public long skip(long n) throws IOException {
- byte[] buf = new byte[(int)Math.min(n,64*1024)];
- return read(buf,0,buf.length);
+ byte[] buf = new byte[(int) Math.min(n, 64 * 1024)];
+ return read(buf, 0, buf.length);
}
@Override
@@ -160,9 +164,10 @@ public synchronized byte[] toByteArray() {
System.arraycopy(data, 0, ret, capacity - pos, pos);
return ret;
}
-
+
/** @author @roadrunner2 */
- @Override public synchronized void write(@NonNull byte[] buf, int off, int len) {
+ @Override
+ public synchronized void write(@NonNull byte[] buf, int off, int len) {
// no point in trying to copy more than capacity; this also simplifies logic below
if (len > capacity) {
off += (len - capacity);
@@ -190,7 +195,5 @@ public synchronized byte[] toByteArray() {
pos += len;
}
}
-
}
-
}
diff --git a/src/main/java/hudson/remoting/Future.java b/src/main/java/hudson/remoting/Future.java
index bc535ad16..f59b3ae7a 100644
--- a/src/main/java/hudson/remoting/Future.java
+++ b/src/main/java/hudson/remoting/Future.java
@@ -1,18 +1,18 @@
/*
* The MIT License
- *
+ *
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -25,17 +25,17 @@
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-//TODO: This Future should be actually deprecated, because it may confuse API users
+// TODO: This Future should be actually deprecated, because it may confuse API users
/**
* Alias to {@link Future}.
*
*
* This alias is defined so that retro-translation won't affect
* the publicly committed signature of the API.
- *
+ *
* @author Kohsuke Kawaguchi
*/
-@SuppressFBWarnings(value = "NM_SAME_SIMPLE_NAME_AS_INTERFACE",
+@SuppressFBWarnings(
+ value = "NM_SAME_SIMPLE_NAME_AS_INTERFACE",
justification = "This class is just an alias, but this alias is a part of public API")
-public interface Future extends java.util.concurrent.Future {
-}
+public interface Future extends java.util.concurrent.Future {}
diff --git a/src/main/java/hudson/remoting/FutureAdapter.java b/src/main/java/hudson/remoting/FutureAdapter.java
index 851c5f275..4c5a334dd 100644
--- a/src/main/java/hudson/remoting/FutureAdapter.java
+++ b/src/main/java/hudson/remoting/FutureAdapter.java
@@ -1,18 +1,18 @@
/*
* The MIT License
- *
+ *
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -33,7 +33,7 @@
*
* @author Kohsuke Kawaguchi
*/
-abstract class FutureAdapter implements Future {
+abstract class FutureAdapter implements Future {
protected final Future core;
protected FutureAdapter(Future core) {
@@ -61,7 +61,8 @@ public X get() throws InterruptedException, ExecutionException {
}
@Override
- public X get(long timeout, @NonNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+ public X get(long timeout, @NonNull TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
return adapt(core.get(timeout, unit));
}
diff --git a/src/main/java/hudson/remoting/HexDump.java b/src/main/java/hudson/remoting/HexDump.java
index bf5c9a3a3..2a30aa5a0 100644
--- a/src/main/java/hudson/remoting/HexDump.java
+++ b/src/main/java/hudson/remoting/HexDump.java
@@ -7,13 +7,14 @@ public class HexDump {
private static final String CODE = "0123456789abcdef";
public static String toHex(byte[] buf) {
- return toHex(buf,0,buf.length);
+ return toHex(buf, 0, buf.length);
}
+
public static String toHex(byte[] buf, int start, int len) {
- StringBuilder r = new StringBuilder(len*2);
+ StringBuilder r = new StringBuilder(len * 2);
boolean inText = false;
- for (int i=0; i= 0x20 && b <= 0x7e) {
if (!inText) {
inText = true;
@@ -26,8 +27,8 @@ public static String toHex(byte[] buf, int start, int len) {
inText = false;
}
r.append("0x");
- r.append(CODE.charAt((b>>4)&15));
- r.append(CODE.charAt(b&15));
+ r.append(CODE.charAt((b >> 4) & 15));
+ r.append(CODE.charAt(b & 15));
if (i < len - 1) {
if (b == 10) {
r.append('\n');
diff --git a/src/main/java/hudson/remoting/IChannel.java b/src/main/java/hudson/remoting/IChannel.java
index 24d6291fc..0737ec21a 100644
--- a/src/main/java/hudson/remoting/IChannel.java
+++ b/src/main/java/hudson/remoting/IChannel.java
@@ -33,5 +33,6 @@
*/
interface IChannel {
Object getProperty(Object key);
+
Object waitForProperty(Object key) throws InterruptedException;
}
diff --git a/src/main/java/hudson/remoting/IReadResolve.java b/src/main/java/hudson/remoting/IReadResolve.java
index c7d87696f..886f704b3 100644
--- a/src/main/java/hudson/remoting/IReadResolve.java
+++ b/src/main/java/hudson/remoting/IReadResolve.java
@@ -1,18 +1,18 @@
/*
* The MIT License
- *
+ *
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
diff --git a/src/main/java/hudson/remoting/ImportedClassLoaderTable.java b/src/main/java/hudson/remoting/ImportedClassLoaderTable.java
index 18353a092..374b082d3 100644
--- a/src/main/java/hudson/remoting/ImportedClassLoaderTable.java
+++ b/src/main/java/hudson/remoting/ImportedClassLoaderTable.java
@@ -1,18 +1,18 @@
/*
* The MIT License
- *
+ *
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -49,7 +49,8 @@ final class ImportedClassLoaderTable {
*/
@NonNull
public ClassLoader get(int oid) {
- return get(RemoteInvocationHandler.wrap(channel, oid, RemoteClassLoader.IClassLoader.class, false, false, false, false));
+ return get(RemoteInvocationHandler.wrap(
+ channel, oid, RemoteClassLoader.IClassLoader.class, false, false, false, false));
}
/**
@@ -61,6 +62,7 @@ public ClassLoader get(int oid) {
@NonNull
public ClassLoader get(@NonNull RemoteClassLoader.IClassLoader classLoaderProxy) {
// we need to be able to use the same hudson.remoting classes, hence delegate to this class loader.
- return classLoaders.computeIfAbsent(classLoaderProxy, proxy -> RemoteClassLoader.create(channel.baseClassLoader, proxy));
+ return classLoaders.computeIfAbsent(
+ classLoaderProxy, proxy -> RemoteClassLoader.create(channel.baseClassLoader, proxy));
}
}
diff --git a/src/main/java/hudson/remoting/InitializeJarCacheMain.java b/src/main/java/hudson/remoting/InitializeJarCacheMain.java
index f3283d71b..0393633aa 100644
--- a/src/main/java/hudson/remoting/InitializeJarCacheMain.java
+++ b/src/main/java/hudson/remoting/InitializeJarCacheMain.java
@@ -27,12 +27,14 @@ public class InitializeJarCacheMain {
* The jar cache directory.
*
*/
- @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", justification = "These file values are provided by users with sufficient administrative permissions to run this utility program.")
+ @SuppressFBWarnings(
+ value = "PATH_TRAVERSAL_IN",
+ justification =
+ "These file values are provided by users with sufficient administrative permissions to run this utility program.")
public static void main(String[] argv) throws Exception {
if (argv.length != 2) {
- throw new IllegalArgumentException(
- "Usage: java -cp agent.jar hudson.remoting.InitializeJarCacheMain " +
- " ");
+ throw new IllegalArgumentException("Usage: java -cp agent.jar hudson.remoting.InitializeJarCacheMain "
+ + " ");
}
File sourceJarDir = new File(argv[0]);
diff --git a/src/main/java/hudson/remoting/InterceptingExecutorService.java b/src/main/java/hudson/remoting/InterceptingExecutorService.java
index 415cfb9e5..fbb2292f6 100644
--- a/src/main/java/hudson/remoting/InterceptingExecutorService.java
+++ b/src/main/java/hudson/remoting/InterceptingExecutorService.java
@@ -46,7 +46,7 @@ public Future> submit(@NonNull Runnable task) {
@Override
@NonNull
public Future submit(@NonNull Runnable task, T result) {
- return super.submit(wrap(task,result));
+ return super.submit(wrap(task, result));
}
@Override
@@ -57,18 +57,22 @@ public List> invokeAll(@NonNull Collection extends Callable>
@Override
@NonNull
- public List> invokeAll(@NonNull Collection extends Callable> tasks, long timeout, @NonNull TimeUnit unit) throws InterruptedException {
+ public List> invokeAll(
+ @NonNull Collection extends Callable> tasks, long timeout, @NonNull TimeUnit unit)
+ throws InterruptedException {
return super.invokeAll(wrap(tasks), timeout, unit);
}
@Override
@NonNull
- public T invokeAny(@NonNull Collection extends Callable> tasks) throws InterruptedException, ExecutionException {
+ public T invokeAny(@NonNull Collection extends Callable> tasks)
+ throws InterruptedException, ExecutionException {
return super.invokeAny(wrap(tasks));
}
@Override
- public T invokeAny(@NonNull Collection extends Callable> tasks, long timeout, @NonNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+ public T invokeAny(@NonNull Collection extends Callable> tasks, long timeout, @NonNull TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
return super.invokeAny(wrap(tasks), timeout, unit);
}
diff --git a/src/main/java/hudson/remoting/JarCache.java b/src/main/java/hudson/remoting/JarCache.java
index 8180da876..3ddd6ce42 100644
--- a/src/main/java/hudson/remoting/JarCache.java
+++ b/src/main/java/hudson/remoting/JarCache.java
@@ -25,9 +25,9 @@ public abstract class JarCache {
* Default JAR cache location for disabled workspace Manager.
*/
public static final File DEFAULT_NOWS_JAR_CACHE_LOCATION =
- new File(System.getProperty("user.home"),".jenkins/cache/jars");
+ new File(System.getProperty("user.home"), ".jenkins/cache/jars");
- //TODO: replace by checked exception
+ // TODO: replace by checked exception
/**
* Gets a default value for {@link FileSystemJarCache} to be initialized on agents.
* @return Created JAR Cache
@@ -55,5 +55,6 @@ public abstract class JarCache {
* URL of the jar file.
*/
@NonNull
- public abstract CompletableFuture resolve(@NonNull Channel channel, long sum1, long sum2) throws IOException, InterruptedException;
+ public abstract CompletableFuture resolve(@NonNull Channel channel, long sum1, long sum2)
+ throws IOException, InterruptedException;
}
diff --git a/src/main/java/hudson/remoting/JarCacheSupport.java b/src/main/java/hudson/remoting/JarCacheSupport.java
index 01685d071..479fed4c3 100644
--- a/src/main/java/hudson/remoting/JarCacheSupport.java
+++ b/src/main/java/hudson/remoting/JarCacheSupport.java
@@ -25,7 +25,7 @@ public abstract class JarCacheSupport extends JarCache {
/**
* Remember in-progress jar file resolution to avoid retrieving the same jar file twice.
*/
- private final ConcurrentMap> inprogress = new ConcurrentHashMap<>();
+ private final ConcurrentMap> inprogress = new ConcurrentHashMap<>();
/**
* Look up the local cache and return URL if found.
@@ -44,8 +44,7 @@ public abstract class JarCacheSupport extends JarCache {
* Throttle the jar downloading activity so that it won't eat up all the channel bandwidth.
*/
private final ExecutorService downloader = newCachingSingleThreadExecutor(
- new NamingThreadFactory(new DaemonThreadFactory(), JarCacheSupport.class.getSimpleName())
- );
+ new NamingThreadFactory(new DaemonThreadFactory(), JarCacheSupport.class.getSimpleName()));
private static ExecutorService newCachingSingleThreadExecutor(ThreadFactory threadFactory) {
ThreadPoolExecutor threadPoolExecutor =
@@ -56,9 +55,10 @@ private static ExecutorService newCachingSingleThreadExecutor(ThreadFactory thre
@Override
@NonNull
- public CompletableFuture resolve(@NonNull final Channel channel, final long sum1, final long sum2) throws IOException, InterruptedException {
- URL jar = lookInCache(channel,sum1, sum2);
- if (jar!=null) {
+ public CompletableFuture resolve(@NonNull final Channel channel, final long sum1, final long sum2)
+ throws IOException, InterruptedException {
+ URL jar = lookInCache(channel, sum1, sum2);
+ if (jar != null) {
// already in the cache
return CompletableFuture.completedFuture(jar);
}
@@ -74,9 +74,9 @@ private CompletableFuture submitDownload(Channel channel, long sum1, long s
downloader.submit(new DownloadRunnable(channel, sum1, sum2, key, promise));
return promise;
}
-
+
private class DownloadRunnable implements Runnable {
-
+
final Channel channel;
final long sum1;
final long sum2;
@@ -90,7 +90,7 @@ public DownloadRunnable(Channel channel, long sum1, long sum2, Checksum key, Com
this.key = key;
this.promise = promise;
}
-
+
@Override
public void run() {
try {
@@ -98,7 +98,8 @@ public void run() {
if (inprogress.remove(key, promise)) {
promise.complete(url);
} else {
- promise.completeExceptionally(new IllegalStateException("Download is (unexpectedly) no longer in progress"));
+ promise.completeExceptionally(
+ new IllegalStateException("Download is (unexpectedly) no longer in progress"));
}
} catch (ChannelClosedException | RequestAbortedException e) {
// the connection was killed while we were still resolving the file
@@ -125,19 +126,19 @@ public void run() {
* Report a failure of the retrieval and allows another thread to retry.
*/
private void bailout(Throwable e) {
- inprogress.remove(key, promise); // this lets another thread to retry later
- promise.completeExceptionally(e); // then tell those who are waiting that we aborted
+ inprogress.remove(key, promise); // this lets another thread to retry later
+ promise.completeExceptionally(e); // then tell those who are waiting that we aborted
}
}
protected JarLoader getJarLoader(Channel channel) throws InterruptedException {
JarLoader jl = channel.getProperty(JarLoader.THEIRS);
- if (jl==null) {// even if two threads run this simultaneously, it is harmless
+ if (jl == null) { // even if two threads run this simultaneously, it is harmless
jl = (JarLoader) channel.waitForRemoteProperty(JarLoader.OURS);
- channel.setProperty(JarLoader.THEIRS,jl);
+ channel.setProperty(JarLoader.THEIRS, jl);
}
return jl;
}
-
+
private static final Logger LOGGER = Logger.getLogger(JarCacheSupport.class.getName());
}
diff --git a/src/main/java/hudson/remoting/JarLoader.java b/src/main/java/hudson/remoting/JarLoader.java
index dcf42263d..15ad9a758 100644
--- a/src/main/java/hudson/remoting/JarLoader.java
+++ b/src/main/java/hudson/remoting/JarLoader.java
@@ -52,6 +52,6 @@ public interface JarLoader {
*/
boolean isPresentOnRemote(Checksum sum);
- String OURS = JarLoader.class.getName()+".ours";
+ String OURS = JarLoader.class.getName() + ".ours";
ChannelProperty THEIRS = new ChannelProperty<>(JarLoader.class, "their JarLoader");
}
diff --git a/src/main/java/hudson/remoting/JarLoaderImpl.java b/src/main/java/hudson/remoting/JarLoaderImpl.java
index 1ed8f3c8c..f1fc0c866 100644
--- a/src/main/java/hudson/remoting/JarLoaderImpl.java
+++ b/src/main/java/hudson/remoting/JarLoaderImpl.java
@@ -25,19 +25,22 @@ class JarLoaderImpl implements JarLoader, SerializableOnlyOverRemoting {
private static final Logger LOGGER = Logger.getLogger(JarLoaderImpl.class.getName());
- private final ConcurrentMap knownJars = new ConcurrentHashMap<>();
+ private final ConcurrentMap knownJars = new ConcurrentHashMap<>();
- private final ConcurrentMap checksums = new ConcurrentHashMap<>();
+ private final ConcurrentMap checksums = new ConcurrentHashMap<>();
private final Set presentOnRemote = Collections.synchronizedSet(new HashSet<>());
@Override
- @SuppressFBWarnings(value = {"URLCONNECTION_SSRF_FD", "PATH_TRAVERSAL_IN"}, justification = "This is only used for managing the jar cache as files, not URLs.")
+ @SuppressFBWarnings(
+ value = {"URLCONNECTION_SSRF_FD", "PATH_TRAVERSAL_IN"},
+ justification = "This is only used for managing the jar cache as files, not URLs.")
public void writeJarTo(long sum1, long sum2, OutputStream sink) throws IOException, InterruptedException {
Checksum k = new Checksum(sum1, sum2);
URL url = knownJars.get(k);
- if (url==null)
- throw new IOException("Unadvertised jar file "+k);
+ if (url == null) {
+ throw new IOException("Unadvertised jar file " + k);
+ }
Channel channel = Channel.current();
if (channel != null) {
@@ -68,14 +71,15 @@ public boolean isPresentOnRemote(Checksum sum) {
@Override
public void notifyJarPresence(long sum1, long sum2) {
- presentOnRemote.add(new Checksum(sum1,sum2));
+ presentOnRemote.add(new Checksum(sum1, sum2));
}
@Override
public void notifyJarPresence(long[] sums) {
synchronized (presentOnRemote) {
- for (int i=0; i candidateCertificates;
private List x509Certificates;
@@ -221,7 +242,11 @@ public void setAuth(String auth) {
* Disables HTTPs Certificate validation of the server when using {@link JnlpAgentEndpointResolver}.
* This option is managed by the {@code -noCertificateCheck} option.
*/
- @Option(name="-noCertificateCheck", aliases = "-disableHttpsCertValidation", forbids = "-cert", usage="Ignore SSL validation errors - use as a last resort only.")
+ @Option(
+ name = "-noCertificateCheck",
+ aliases = "-disableHttpsCertValidation",
+ forbids = "-cert",
+ usage = "Ignore SSL validation errors - use as a last resort only.")
public boolean noCertificateCheck = false;
private HostnameVerifier hostnameVerifier;
@@ -236,26 +261,35 @@ public void setAuth(String auth) {
* @deprecated removed without replacement
*/
@Deprecated
- @Option(name="-connectTo",usage="(deprecated) make a TCP connection to the given host and port, then start communication.",metaVar="HOST:PORT")
+ @Option(
+ name = "-connectTo",
+ usage = "(deprecated) make a TCP connection to the given host and port, then start communication.",
+ metaVar = "HOST:PORT")
public void setConnectTo(String target) {
String[] tokens = target.split(":");
- if(tokens.length!=2) {
- System.err.println("Illegal parameter: "+target);
+ if (tokens.length != 2) {
+ System.err.println("Illegal parameter: " + target);
System.exit(1);
}
- connectionTarget = new InetSocketAddress(tokens[0],Integer.parseInt(tokens[1]));
+ connectionTarget = new InetSocketAddress(tokens[0], Integer.parseInt(tokens[1]));
System.err.println(
"WARNING: The \"-connectTo\" argument is deprecated and will be removed without replacement in a future release.");
}
- @Option(name="-noReconnect",aliases="-noreconnect",usage="Doesn't try to reconnect when a communication fail, and exit instead")
+ @Option(
+ name = "-noReconnect",
+ aliases = "-noreconnect",
+ usage = "Doesn't try to reconnect when a communication fail, and exit instead")
public boolean noReconnect = false;
- @Option(name="-noReconnectAfter",usage = "Bail out after the given time after the first attempt to reconnect", handler = DurationOptionHandler.class, forbids = "-noReconnect")
+ @Option(
+ name = "-noReconnectAfter",
+ usage = "Bail out after the given time after the first attempt to reconnect",
+ handler = DurationOptionHandler.class,
+ forbids = "-noReconnect")
public Duration noReconnectAfter;
- @Option(name = "-noKeepAlive",
- usage = "Disable TCP socket keep alive on connection to the controller.")
+ @Option(name = "-noKeepAlive", usage = "Disable TCP socket keep alive on connection to the controller.")
public boolean noKeepAlive = false;
/**
@@ -267,7 +301,8 @@ public void setConnectTo(String target) {
* Jenkins specifics: This working directory is expected to be equal to the agent root specified in Jenkins configuration.
* @since 3.8
*/
- @Option(name = "-workDir",
+ @Option(
+ name = "-workDir",
usage = "Declares the working directory of the remoting instance (stores cache and logs by default)")
@CheckForNull
public File workDir = null;
@@ -279,7 +314,8 @@ public void setConnectTo(String target) {
* storage directory if the default {@code remoting} directory is consumed by other stuff.
* @since 3.8
*/
- @Option(name = "-internalDir",
+ @Option(
+ name = "-internalDir",
usage = "Specifies a name of the internal files within a working directory ('remoting' by default)",
depends = "-workDir")
@NonNull
@@ -291,12 +327,14 @@ public void setConnectTo(String target) {
* (e.g. if a filesystem mount gets disconnected).
* @since 3.8
*/
- @Option(name = "-failIfWorkDirIsMissing",
+ @Option(
+ name = "-failIfWorkDirIsMissing",
usage = "Fails the initialization if the requested workDir or internalDir are missing ('false' by default)",
depends = "-workDir")
public boolean failIfWorkDirIsMissing = WorkDirManager.DEFAULT_FAIL_IF_WORKDIR_IS_MISSING;
-
- @Option(name = "-tunnel",
+
+ @Option(
+ name = "-tunnel",
metaVar = "HOST:PORT",
usage = "Connect to the specified host and port, instead of connecting directly to Jenkins. "
+ "Useful when connection to Jenkins needs to be tunneled. Can be also HOST: or :PORT, "
@@ -323,19 +361,17 @@ public void setHeadlessMode(boolean headlessMode) {
@Option(name = "-url", usage = "Specify the Jenkins root URLs to connect to.")
public List urls = new ArrayList<>();
- @Option(name = "-webSocket",
+ @Option(
+ name = "-webSocket",
usage = "Make a WebSocket connection to Jenkins rather than using the TCP port.",
depends = "-url",
- forbids = {
- "-direct",
- "-tunnel",
- "-credentials",
- "-noKeepAlive"
- })
+ forbids = {"-direct", "-tunnel", "-credentials", "-noKeepAlive"})
public boolean webSocket;
- @Option(name = "-webSocketHeader",
- usage = "Additional WebSocket header to set, eg for authenticating with reverse proxies. To specify multiple headers, call this flag multiple times, one with each header",
+ @Option(
+ name = "-webSocketHeader",
+ usage =
+ "Additional WebSocket header to set, eg for authenticating with reverse proxies. To specify multiple headers, call this flag multiple times, one with each header",
metaVar = "NAME=VALUE",
depends = "-webSocket")
public Map webSocketHeaders;
@@ -344,12 +380,14 @@ public void setHeadlessMode(boolean headlessMode) {
* Connect directly to the TCP port specified, skipping the HTTP(S) connection parameter download.
* @since 3.34
*/
- @Option(name = "-direct",
+ @Option(
+ name = "-direct",
metaVar = "HOST:PORT",
aliases = "-directConnection",
depends = "-instanceIdentity",
forbids = {"-jnlpUrl", "-url", "-tunnel"},
- usage = "Connect directly to this TCP agent port, skipping the HTTP(S) connection parameter download. For example, \"myjenkins:50000\".")
+ usage =
+ "Connect directly to this TCP agent port, skipping the HTTP(S) connection parameter download. For example, \"myjenkins:50000\".")
public String directConnection;
/**
@@ -357,9 +395,11 @@ public void setHeadlessMode(boolean headlessMode) {
* @see Instance Identity
* @since 3.34
*/
- @Option(name = "-instanceIdentity",
+ @Option(
+ name = "-instanceIdentity",
depends = "-direct",
- usage = "The base64 encoded InstanceIdentity byte array of the Jenkins controller. When this is set, the agent skips connecting to an HTTP(S) port for connection info.")
+ usage =
+ "The base64 encoded InstanceIdentity byte array of the Jenkins controller. When this is set, the agent skips connecting to an HTTP(S) port for connection info.")
public String instanceIdentity;
/**
@@ -368,7 +408,8 @@ public void setHeadlessMode(boolean headlessMode) {
* it knows. Use this to limit the protocol list.
* @since 3.34
*/
- @Option(name = "-protocols",
+ @Option(
+ name = "-protocols",
depends = {"-direct"},
usage = "Specify the remoting protocols to attempt when instanceIdentity is provided.")
public List protocols = new ArrayList<>();
@@ -377,14 +418,14 @@ public void setHeadlessMode(boolean headlessMode) {
* Shows help message and then exits
* @since 3.36
*/
- @Option(name="-help",usage="Show this help message")
+ @Option(name = "-help", usage = "Show this help message")
public boolean showHelp = false;
/**
* Shows version information and then exits
* @since 3.36
*/
- @Option(name="-version",usage="Shows the version of the remoting jar and then exits")
+ @Option(name = "-version", usage = "Shows the version of the remoting jar and then exits")
public boolean showVersion = false;
/**
@@ -420,11 +461,13 @@ public static void main(String... args) throws IOException, InterruptedException
}
}
- @SuppressFBWarnings(value = "DM_DEFAULT_ENCODING", justification = "log file, just like console output, should be in platform default encoding")
+ @SuppressFBWarnings(
+ value = "DM_DEFAULT_ENCODING",
+ justification = "log file, just like console output, should be in platform default encoding")
public void run() throws CmdLineException, IOException, InterruptedException {
if (showVersion) {
String version = Util.getVersion();
- if(version != null) {
+ if (version != null) {
System.out.println(version);
}
return;
@@ -456,9 +499,11 @@ private synchronized void initialize() throws IOException {
throw new IllegalStateException("double initialization");
}
// Create and verify working directory and logging
- // TODO: The pass-through for the JNLP mode has been added in JENKINS-39817. But we still need to keep this parameter in
+ // TODO: The pass-through for the JNLP mode has been added in JENKINS-39817. But we still need to keep this
+ // parameter in
// consideration for other modes (TcpServer, TcpClient, etc.) to retain the legacy behavior.
- // On the other hand, in such case there is no need to invoke WorkDirManager and handle the double initialization logic
+ // On the other hand, in such case there is no need to invoke WorkDirManager and handle the double
+ // initialization logic
final WorkDirManager workDirManager = WorkDirManager.getInstance();
final Path internalDirPath = workDirManager.initializeWorkDir(workDir, internalDir, failIfWorkDirIsMissing);
if (agentLog != null) {
@@ -506,25 +551,30 @@ private void createX509Certificates() {
// larger
// than 64kb we can revisit the upper bound.
cert = new byte[(int) length];
- int read = fis.read(cert);
- if (cert.length != read) {
- LOGGER.log(Level.WARNING, "Only read {0} bytes from {1}, expected to read {2}",
- new Object[]{read, file, cert.length});
- // skip it
- continue;
- }
+ int read = fis.read(cert);
+ if (cert.length != read) {
+ LOGGER.log(
+ Level.WARNING,
+ "Only read {0} bytes from {1}, expected to read {2}",
+ new Object[] {read, file, cert.length});
+ // skip it
+ continue;
+ }
} catch (IOException e) {
LOGGER.log(Level.WARNING, e, () -> "Could not read certificate from " + file);
continue;
}
} else {
if (file.isFile()) {
- LOGGER.log(Level.WARNING,
- "Could not read certificate from {0}. File size is not within " +
- "the expected range for a PEM encoded X.509 certificate",
+ LOGGER.log(
+ Level.WARNING,
+ "Could not read certificate from {0}. File size is not within "
+ + "the expected range for a PEM encoded X.509 certificate",
file.getAbsolutePath());
} else {
- LOGGER.log(Level.WARNING, "Could not read certificate from {0}. File not found",
+ LOGGER.log(
+ Level.WARNING,
+ "Could not read certificate from {0}. File not found",
file.getAbsolutePath());
}
continue;
@@ -678,8 +728,11 @@ private void runAsInboundAgent() throws CmdLineException, IOException, Interrupt
/**
* Parses the connection arguments from JNLP file given in the URL.
*/
- @SuppressFBWarnings(value = {"CIPHER_INTEGRITY", "STATIC_IV"}, justification = "Integrity not needed here. IV used for decryption only, loaded from encryptor.")
- private List parseJnlpArguments() throws ParserConfigurationException, SAXException, IOException, InterruptedException {
+ @SuppressFBWarnings(
+ value = {"CIPHER_INTEGRITY", "STATIC_IV"},
+ justification = "Integrity not needed here. IV used for decryption only, loaded from encryptor.")
+ private List parseJnlpArguments()
+ throws ParserConfigurationException, SAXException, IOException, InterruptedException {
initialize();
if (secret != null) {
agentJnlpURL = new URL(agentJnlpURL + "?encrypt=true");
@@ -691,21 +744,25 @@ private List parseJnlpArguments() throws ParserConfigurationException, S
while (true) {
URLConnection con = null;
try {
- con = JnlpAgentEndpointResolver.openURLConnection(agentJnlpURL, null, agentJnlpCredentials, proxyCredentials, sslSocketFactory, hostnameVerifier);
+ con = JnlpAgentEndpointResolver.openURLConnection(
+ agentJnlpURL, null, agentJnlpCredentials, proxyCredentials, sslSocketFactory, hostnameVerifier);
con.connect();
if (con instanceof HttpURLConnection) {
HttpURLConnection http = (HttpURLConnection) con;
- if(http.getResponseCode()>=400)
+ if (http.getResponseCode() >= 400) {
// got the error code. report that (such as 401)
- throw new IOException("Failed to load "+ agentJnlpURL +": "+http.getResponseCode()+" "+http.getResponseMessage());
+ throw new IOException("Failed to load " + agentJnlpURL + ": " + http.getResponseCode() + " "
+ + http.getResponseMessage());
+ }
}
Document dom;
// check if this URL points to a .jnlp file
String contentType = con.getHeaderField("Content-Type");
- String expectedContentType = secret == null ? "application/x-java-jnlp-file" : "application/octet-stream";
+ String expectedContentType =
+ secret == null ? "application/x-java-jnlp-file" : "application/octet-stream";
InputStream input = con.getInputStream();
if (secret != null) {
byte[] payload = input.readAllBytes();
@@ -713,21 +770,25 @@ private List parseJnlpArguments() throws ParserConfigurationException, S
try {
Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding");
- cipher.init(Cipher.DECRYPT_MODE,
- new SecretKeySpec(fromHexString(secret.substring(0, Math.min(secret.length(), 32))), "AES"),
- new IvParameterSpec(payload,0,16));
- byte[] decrypted = cipher.doFinal(payload,16,payload.length-16);
+ cipher.init(
+ Cipher.DECRYPT_MODE,
+ new SecretKeySpec(
+ fromHexString(secret.substring(0, Math.min(secret.length(), 32))), "AES"),
+ new IvParameterSpec(payload, 0, 16));
+ byte[] decrypted = cipher.doFinal(payload, 16, payload.length - 16);
input = new ByteArrayInputStream(decrypted);
} catch (GeneralSecurityException x) {
throw new IOException("Failed to decrypt the JNLP file. Invalid secret key?", x);
}
}
- if(contentType==null || !contentType.startsWith(expectedContentType)) {
- // load DOM anyway, but if it fails to parse, that's probably because this is not an XML file to begin with.
+ if (contentType == null || !contentType.startsWith(expectedContentType)) {
+ // load DOM anyway, but if it fails to parse, that's probably because this is not an XML file to
+ // begin with.
try {
dom = loadDom(input);
} catch (SAXException | IOException e) {
- throw new IOException(agentJnlpURL +" doesn't look like a JNLP file; content type was "+contentType);
+ throw new IOException(
+ agentJnlpURL + " doesn't look like a JNLP file; content type was " + contentType);
}
} else {
dom = loadDom(input);
@@ -736,22 +797,29 @@ private List parseJnlpArguments() throws ParserConfigurationException, S
// exec into the JNLP launcher, to fetch the connection parameter through JNLP.
NodeList argElements = dom.getElementsByTagName("argument");
List jnlpArgs = new ArrayList<>();
- for( int i=0; i parseJnlpArguments() throws ParserConfigurationException, S
// from hudson.Util
private static byte[] fromHexString(String data) {
byte[] r = new byte[data.length() / 2];
- for (int i = 0; i < data.length(); i += 2)
+ for (int i = 0; i < data.length(); i += 2) {
r[i / 2] = (byte) Integer.parseInt(data.substring(i, i + 2), 16);
+ }
return r;
}
@@ -786,15 +855,18 @@ static Document loadDom(InputStream is) throws ParserConfigurationException, SAX
* then accepts one TCP connection.
*/
@Deprecated
- @SuppressFBWarnings(value = {"UNENCRYPTED_SERVER_SOCKET", "DM_DEFAULT_ENCODING", "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD"}, justification = "This is an old, insecure mechanism that should be removed. port number file should be in platform default encoding. Laucher instance is created only once.")
+ @SuppressFBWarnings(
+ value = {"UNENCRYPTED_SERVER_SOCKET", "DM_DEFAULT_ENCODING", "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD"},
+ justification =
+ "This is an old, insecure mechanism that should be removed. port number file should be in platform default encoding. Laucher instance is created only once.")
private void runAsTcpServer() throws IOException, InterruptedException {
// accept just one connection and that's it.
// when we are done, remove the port file to avoid stale port file
Socket s;
- try (ServerSocket ss = new ServerSocket(0,1)) {
+ try (ServerSocket ss = new ServerSocket(0, 1)) {
// if no one connects for too long, assume something went wrong
// and avoid hanging forever
- ss.setSoTimeout(30*1000);
+ ss.setSoTimeout(30 * 1000);
// write a port file to report the port number
try (FileWriter w = new FileWriter(tcpPortFile)) {
@@ -819,56 +891,64 @@ private void runOnSocket(Socket s) throws IOException, InterruptedException {
s.setKeepAlive(true);
// we take care of buffering on our own
s.setTcpNoDelay(true);
- main(new BufferedInputStream(SocketChannelStream.in(s)),
- new BufferedOutputStream(SocketChannelStream.out(s)), mode,ping,
- jarCache != null ? new FileSystemJarCache(jarCache,true) : null);
+ main(
+ new BufferedInputStream(SocketChannelStream.in(s)),
+ new BufferedOutputStream(SocketChannelStream.out(s)),
+ mode,
+ ping,
+ jarCache != null ? new FileSystemJarCache(jarCache, true) : null);
}
/**
* Connects to the given TCP port and then start running
*/
- @SuppressFBWarnings(value = {"UNENCRYPTED_SOCKET", "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD"}, justification = "This implements an old, insecure connection mechanism. Laucher instance is created only once.")
+ @SuppressFBWarnings(
+ value = {"UNENCRYPTED_SOCKET", "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD"},
+ justification =
+ "This implements an old, insecure connection mechanism. Laucher instance is created only once.")
@Deprecated
private void runAsTcpClient() throws IOException, InterruptedException {
// if no one connects for too long, assume something went wrong
// and avoid hanging forever
- Socket s = new Socket(connectionTarget.getAddress(),connectionTarget.getPort());
+ Socket s = new Socket(connectionTarget.getAddress(), connectionTarget.getPort());
Launcher.communicationProtocolName = "TCP (remote: client)";
runOnSocket(s);
}
- @SuppressFBWarnings(value = {"ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", "DMI_RANDOM_USED_ONLY_ONCE"}, justification = "Laucher instance is created only once.")
+ @SuppressFBWarnings(
+ value = {"ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", "DMI_RANDOM_USED_ONLY_ONCE"},
+ justification = "Laucher instance is created only once.")
private void runWithStdinStdout() throws IOException, InterruptedException {
// use stdin/stdout for channel communication
ttyCheck();
if (isWindows()) {
/*
- To prevent the dead lock between GetFileType from _ioinit in C runtime and blocking read that ChannelReaderThread
- would do on stdin, load the crypto DLL first.
-
- This is a band-aid solution to the problem. Still searching for more fundamental fix.
-
- 02f1e750 7c90d99a ntdll!KiFastSystemCallRet
- 02f1e754 7c810f63 ntdll!NtQueryVolumeInformationFile+0xc
- 02f1e784 77c2c9f9 kernel32!GetFileType+0x7e
- 02f1e7e8 77c1f01d msvcrt!_ioinit+0x19f
- 02f1e88c 7c90118a msvcrt!__CRTDLL_INIT+0xac
- 02f1e8ac 7c91c4fa ntdll!LdrpCallInitRoutine+0x14
- 02f1e9b4 7c916371 ntdll!LdrpRunInitializeRoutines+0x344
- 02f1ec60 7c9164d3 ntdll!LdrpLoadDll+0x3e5
- 02f1ef08 7c801bbd ntdll!LdrLoadDll+0x230
- 02f1ef70 7c801d72 kernel32!LoadLibraryExW+0x18e
- 02f1ef84 7c801da8 kernel32!LoadLibraryExA+0x1f
- 02f1efa0 77de8830 kernel32!LoadLibraryA+0x94
- 02f1f05c 6d3eb1be ADVAPI32!CryptAcquireContextA+0x512
- WARNING: Stack unwind information not available. Following frames may be wrong.
- 02f1f13c 6d99c844 java_6d3e0000!Java_sun_security_provider_NativeSeedGenerator_nativeGenerateSeed+0x6e
-
- see http://weblogs.java.net/blog/kohsuke/archive/2009/09/28/reading-stdin-may-cause-your-jvm-hang
- for more details
- */
+ To prevent the dead lock between GetFileType from _ioinit in C runtime and blocking read that ChannelReaderThread
+ would do on stdin, load the crypto DLL first.
+
+ This is a band-aid solution to the problem. Still searching for more fundamental fix.
+
+ 02f1e750 7c90d99a ntdll!KiFastSystemCallRet
+ 02f1e754 7c810f63 ntdll!NtQueryVolumeInformationFile+0xc
+ 02f1e784 77c2c9f9 kernel32!GetFileType+0x7e
+ 02f1e7e8 77c1f01d msvcrt!_ioinit+0x19f
+ 02f1e88c 7c90118a msvcrt!__CRTDLL_INIT+0xac
+ 02f1e8ac 7c91c4fa ntdll!LdrpCallInitRoutine+0x14
+ 02f1e9b4 7c916371 ntdll!LdrpRunInitializeRoutines+0x344
+ 02f1ec60 7c9164d3 ntdll!LdrpLoadDll+0x3e5
+ 02f1ef08 7c801bbd ntdll!LdrLoadDll+0x230
+ 02f1ef70 7c801d72 kernel32!LoadLibraryExW+0x18e
+ 02f1ef84 7c801da8 kernel32!LoadLibraryExA+0x1f
+ 02f1efa0 77de8830 kernel32!LoadLibraryA+0x94
+ 02f1f05c 6d3eb1be ADVAPI32!CryptAcquireContextA+0x512
+ WARNING: Stack unwind information not available. Following frames may be wrong.
+ 02f1f13c 6d99c844 java_6d3e0000!Java_sun_security_provider_NativeSeedGenerator_nativeGenerateSeed+0x6e
+
+ see http://weblogs.java.net/blog/kohsuke/archive/2009/09/28/reading-stdin-may-cause-your-jvm-hang
+ for more details
+ */
new SecureRandom().nextBoolean();
}
@@ -880,7 +960,7 @@ private void runWithStdinStdout() throws IOException, InterruptedException {
Launcher.communicationProtocolName = "Standard in/out";
// System.in/out appear to be already buffered (at least that was the case in Linux and Windows as of Java6)
// so we are not going to double-buffer these.
- main(System.in, os, mode, ping, jarCache != null ? new FileSystemJarCache(jarCache,true) : null);
+ main(System.in, os, mode, ping, jarCache != null ? new FileSystemJarCache(jarCache, true) : null);
}
/**
@@ -889,13 +969,12 @@ private void runWithStdinStdout() throws IOException, InterruptedException {
*/
private static void ttyCheck() {
final Console console = System.console();
- if(console != null) {
+ if (console != null) {
// we seem to be running from interactive console. issue a warning.
// but since this diagnosis could be wrong, go on and do what we normally do anyway. Don't exit.
- System.out.println(
- "WARNING: Are you running agent from an interactive console?\n" +
- "If so, you are probably using it incorrectly.\n" +
- "See https://wiki.jenkins.io/display/JENKINS/Launching+agent+from+console");
+ System.out.println("WARNING: Are you running agent from an interactive console?\n"
+ + "If so, you are probably using it incorrectly.\n"
+ + "See https://wiki.jenkins.io/display/JENKINS/Launching+agent+from+console");
}
}
@@ -903,8 +982,9 @@ public static void main(InputStream is, OutputStream os) throws IOException, Int
main(is, os, Channel.Mode.BINARY);
}
- public static void main(InputStream is, OutputStream os, Channel.Mode mode) throws IOException, InterruptedException {
- main(is,os,mode,false);
+ public static void main(InputStream is, OutputStream os, Channel.Mode mode)
+ throws IOException, InterruptedException {
+ main(is, os, mode, false);
}
/**
@@ -912,7 +992,8 @@ public static void main(InputStream is, OutputStream os, Channel.Mode mode) thro
* Use {@link #main(InputStream, OutputStream, Channel.Mode, boolean, JarCache)}
*/
@Deprecated
- public static void main(InputStream is, OutputStream os, Channel.Mode mode, boolean performPing) throws IOException, InterruptedException {
+ public static void main(InputStream is, OutputStream os, Channel.Mode mode, boolean performPing)
+ throws IOException, InterruptedException {
main(is, os, mode, performPing, null);
}
/**
@@ -921,26 +1002,33 @@ public static void main(InputStream is, OutputStream os, Channel.Mode mode, bool
* If {@code null}, a default value will be used.
* @since 2.24
*/
- public static void main(InputStream is, OutputStream os, Channel.Mode mode, boolean performPing, @CheckForNull JarCache cache) throws IOException, InterruptedException {
+ public static void main(
+ InputStream is, OutputStream os, Channel.Mode mode, boolean performPing, @CheckForNull JarCache cache)
+ throws IOException, InterruptedException {
ExecutorService executor = Executors.newCachedThreadPool();
- ChannelBuilder cb = new ChannelBuilder("channel", executor)
- .withMode(mode)
- .withJarCacheOrDefault(cache);
+ ChannelBuilder cb =
+ new ChannelBuilder("channel", executor).withMode(mode).withJarCacheOrDefault(cache);
// expose StandardOutputStream as a channel property, which is a better way to make this available
// to the user of Channel than Channel#getUnderlyingOutput()
- if (os instanceof StandardOutputStream)
- cb.withProperty(StandardOutputStream.class,os);
+ if (os instanceof StandardOutputStream) {
+ cb.withProperty(StandardOutputStream.class, os);
+ }
Channel channel = cb.build(is, os);
System.err.println("channel started");
// Both settings are available since remoting-2.0
- long timeout = 1000 * Long.parseLong(
- System.getProperty("hudson.remoting.Launcher.pingTimeoutSec", "240")),
- interval = 1000 * Long.parseLong(
- System.getProperty("hudson.remoting.Launcher.pingIntervalSec", /* was "600" but this duplicates ChannelPinger */ "0"));
- Logger.getLogger(PingThread.class.getName()).log(Level.FINE, "performPing={0} timeout={1} interval={2}", new Object[] {performPing, timeout, interval});
+ long timeout = 1000 * Long.parseLong(System.getProperty("hudson.remoting.Launcher.pingTimeoutSec", "240")),
+ interval =
+ 1000
+ * Long.parseLong(System.getProperty(
+ "hudson.remoting.Launcher.pingIntervalSec", /* was "600" but this duplicates ChannelPinger */
+ "0"));
+ Logger.getLogger(PingThread.class.getName())
+ .log(Level.FINE, "performPing={0} timeout={1} interval={2}", new Object[] {
+ performPing, timeout, interval
+ });
if (performPing && timeout > 0 && interval > 0) {
new PingThread(channel, timeout, interval) {
@Deprecated
@@ -949,8 +1037,11 @@ protected void onDead() {
System.err.println("Ping failed. Terminating");
System.exit(-1);
}
+
@Override
- @SuppressFBWarnings(value = "INFORMATION_EXPOSURE_THROUGH_AN_ERROR_MESSAGE", justification = "Prints the agent-side message to the agent log before exiting.")
+ @SuppressFBWarnings(
+ value = "INFORMATION_EXPOSURE_THROUGH_AN_ERROR_MESSAGE",
+ justification = "Prints the agent-side message to the agent log before exiting.")
protected void onDead(Throwable cause) {
System.err.println("Ping failed. Terminating");
cause.printStackTrace();
@@ -964,7 +1055,7 @@ protected void onDead(Throwable cause) {
}
public static boolean isWindows() {
- return File.pathSeparatorChar==';';
+ return File.pathSeparatorChar == ';';
}
/**
@@ -983,7 +1074,9 @@ private static String computeVersion() {
Properties props = new Properties();
InputStream is = Launcher.class.getResourceAsStream(JENKINS_VERSION_PROP_FILE);
if (is == null) {
- LOGGER.log(Level.FINE, "Cannot locate the {0} resource file. Hudson/Jenkins version is unknown",
+ LOGGER.log(
+ Level.FINE,
+ "Cannot locate the {0} resource file. Hudson/Jenkins version is unknown",
JENKINS_VERSION_PROP_FILE);
return UNKNOWN_JENKINS_VERSION_STR;
}
@@ -1010,13 +1103,7 @@ private static void closeWithLogOnly(Closeable stream, String name) {
private Engine createEngine() throws IOException {
LOGGER.log(Level.INFO, "Setting up agent: {0}", name);
Engine engine = new Engine(
- new CuiListener(),
- urls,
- secret,
- name,
- directConnection,
- instanceIdentity,
- new HashSet<>(protocols));
+ new CuiListener(), urls, secret, name, directConnection, instanceIdentity, new HashSet<>(protocols));
engine.setWebSocket(webSocket);
if (webSocketHeaders != null) {
engine.setWebSocketHeaders(webSocketHeaders);
diff --git a/src/main/java/hudson/remoting/LocalChannel.java b/src/main/java/hudson/remoting/LocalChannel.java
index 496368c10..263c86b03 100644
--- a/src/main/java/hudson/remoting/LocalChannel.java
+++ b/src/main/java/hudson/remoting/LocalChannel.java
@@ -1,18 +1,18 @@
/*
* The MIT License
- *
+ *
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -31,7 +31,7 @@
/**
* {@link VirtualChannel} that performs computation on the local JVM.
- *
+ *
* @author Kohsuke Kawaguchi
*/
public class LocalChannel implements VirtualChannel {
@@ -42,12 +42,12 @@ public LocalChannel(ExecutorService executor) {
}
@Override
- public V call(Callable callable) throws T {
+ public V call(Callable callable) throws T {
return callable.call();
}
@Override
- public Future callAsync(@NonNull final Callable callable) {
+ public Future callAsync(@NonNull final Callable callable) {
final java.util.concurrent.Future f = executor.submit(() -> {
try {
return callable.call();
@@ -80,7 +80,8 @@ public V get() throws InterruptedException, ExecutionException {
}
@Override
- public V get(long timeout, @NonNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+ public V get(long timeout, @NonNull TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
return f.get(timeout, unit);
}
};
diff --git a/src/main/java/hudson/remoting/MimicException.java b/src/main/java/hudson/remoting/MimicException.java
index 07440b83a..5bdd92203 100644
--- a/src/main/java/hudson/remoting/MimicException.java
+++ b/src/main/java/hudson/remoting/MimicException.java
@@ -19,13 +19,15 @@
@Restricted(DoNotUse.class)
class MimicException extends Exception {
private final String className;
+
MimicException(Throwable cause) {
super(cause.getMessage());
className = cause.getClass().getName();
setStackTrace(cause.getStackTrace());
- if (cause.getCause()!=null)
+ if (cause.getCause() != null) {
initCause(new MimicException(cause.getCause()));
+ }
}
@Override
@@ -37,13 +39,16 @@ public String toString() {
@Nullable
public static Throwable make(@NonNull Channel ch, @Nullable Throwable cause) {
- if (cause == null) return null;
+ if (cause == null) {
+ return null;
+ }
// make sure the remoting layer of the other end supports this
- if (ch.remoteCapability.hasMimicException())
+ if (ch.remoteCapability.hasMimicException()) {
return new MimicException(cause);
- else
+ } else {
return cause;
+ }
}
private static final long serialVersionUID = 1L;
diff --git a/src/main/java/hudson/remoting/MultiClassLoaderSerializer.java b/src/main/java/hudson/remoting/MultiClassLoaderSerializer.java
index 9ddea740d..fd609b7a4 100644
--- a/src/main/java/hudson/remoting/MultiClassLoaderSerializer.java
+++ b/src/main/java/hudson/remoting/MultiClassLoaderSerializer.java
@@ -34,7 +34,7 @@ static final class Output extends ObjectOutputStream {
/**
* Encountered Classloaders, to their indices.
*/
- private final Map classLoaders = new HashMap<>();
+ private final Map classLoaders = new HashMap<>();
Output(Channel channel, OutputStream out) throws IOException {
super(out);
@@ -45,17 +45,17 @@ static final class Output extends ObjectOutputStream {
protected void annotateClass(Class> c) throws IOException {
AnonymousClassWarnings.check(c);
ClassLoader cl = c.getClassLoader();
- if (cl==null) {// bootstrap classloader. no need to export.
+ if (cl == null) { // bootstrap classloader. no need to export.
writeInt(TAG_SYSTEMCLASSLOADER);
return;
}
Integer idx = classLoaders.get(cl);
- if (idx==null) {
- classLoaders.put(cl,classLoaders.size());
+ if (idx == null) {
+ classLoaders.put(cl, classLoaders.size());
if (cl instanceof RemoteClassLoader) {
int oid = ((RemoteClassLoader) cl).getOid(channel);
- if (oid>=0) {
+ if (oid >= 0) {
// this classloader came from where we are sending this classloader to.
writeInt(TAG_LOCAL_CLASSLOADER);
writeInt(oid);
@@ -64,10 +64,11 @@ protected void annotateClass(Class> c) throws IOException {
}
// tell the receiving side that they need to import a new classloader
- // this reference count is released when RemoteInvocationHandler backing RemoteClassLoader.IClassLoader is GCed on the remote node.
+ // this reference count is released when RemoteInvocationHandler backing RemoteClassLoader.IClassLoader
+ // is GCed on the remote node.
writeInt(TAG_EXPORTED_CLASSLOADER);
- writeInt(RemoteClassLoader.exportId(cl,channel));
- } else {// reference to a classloader that's already written
+ writeInt(RemoteClassLoader.exportId(cl, channel));
+ } else { // reference to a classloader that's already written
writeInt(idx);
}
}
@@ -95,28 +96,30 @@ private ClassLoader readClassLoader() throws IOException, ClassNotFoundException
ClassLoader cl;
int code = readInt();
switch (code) {
- case TAG_SYSTEMCLASSLOADER:
- return null;
-
- case TAG_LOCAL_CLASSLOADER:
- Object proxyObject;
- int oid = readInt();
- try {
- proxyObject = channel.getExportedObject(oid);
- } catch (ExecutionException ex) {
- throw new IOException("Cannot locate RemoteClassLoader.ClassLoaderProxy(" +
- oid + ") in the channel exported table", ex);
- }
- cl = ((RemoteClassLoader.ClassLoaderProxy)proxyObject).cl;
- classLoaders.add(cl);
- return cl;
-
- case TAG_EXPORTED_CLASSLOADER:
- cl = channel.importedClassLoaders.get(readInt());
- classLoaders.add(cl);
- return cl;
- default:
- return classLoaders.get(code);
+ case TAG_SYSTEMCLASSLOADER:
+ return null;
+
+ case TAG_LOCAL_CLASSLOADER:
+ Object proxyObject;
+ int oid = readInt();
+ try {
+ proxyObject = channel.getExportedObject(oid);
+ } catch (ExecutionException ex) {
+ throw new IOException(
+ "Cannot locate RemoteClassLoader.ClassLoaderProxy(" + oid
+ + ") in the channel exported table",
+ ex);
+ }
+ cl = ((RemoteClassLoader.ClassLoaderProxy) proxyObject).cl;
+ classLoaders.add(cl);
+ return cl;
+
+ case TAG_EXPORTED_CLASSLOADER:
+ cl = channel.importedClassLoaders.get(readInt());
+ classLoaders.add(cl);
+ return cl;
+ default:
+ return classLoaders.get(code);
}
}
@@ -140,9 +143,10 @@ protected Class> resolveProxyClass(String[] interfaces) throws IOException, Cl
ClassLoader cl = readClassLoader();
Class>[] classes = new Class[interfaces.length];
- for (int i = 0; i < interfaces.length; i++)
+ for (int i = 0; i < interfaces.length; i++) {
// TODO: handle null classloader as a System one?
classes[i] = Class.forName(interfaces[i], false, cl);
+ }
/*
dead lock prevention.
@@ -162,15 +166,16 @@ protected Class> resolveProxyClass(String[] interfaces) throws IOException, Cl
So this is somewhat hack-ish, but in this change we look for a specific
proxy type that we use and resolve them outside Proxy.getProxyClass.
*/
- if (classes.length==2 && classes[0]==JarLoader.class && classes[1]==IReadResolve.class)
+ if (classes.length == 2 && classes[0] == JarLoader.class && classes[1] == IReadResolve.class) {
return Channel.jarLoaderProxy;
+ }
return Proxy.getProxyClass(cl, classes);
}
@Override
protected Object resolveObject(Object obj) throws IOException {
- if(obj instanceof URL){
+ if (obj instanceof URL) {
// SECURITY-637, URL deserialization could lead to DNS query
return URLDeserializationHelper.wrapIfRequired((URL) obj);
}
diff --git a/src/main/java/hudson/remoting/NoProxyEvaluator.java b/src/main/java/hudson/remoting/NoProxyEvaluator.java
index 9d267d88c..5edd26f1d 100644
--- a/src/main/java/hudson/remoting/NoProxyEvaluator.java
+++ b/src/main/java/hudson/remoting/NoProxyEvaluator.java
@@ -92,16 +92,15 @@ private static String getEnvironmentValue() {
}
private boolean matchesIpAddress(InetAddress hostAddress) {
- return noProxyIpAddresses.stream().
- anyMatch(inetAddress -> inetAddress.equals(hostAddress));
+ return noProxyIpAddresses.stream().anyMatch(inetAddress -> inetAddress.equals(hostAddress));
}
private void processSpecificationsIntoTypes(String noProxySpecification) {
noProxySpecification = noProxySpecification.trim();
String[] noProxySpecifications = splitComponents(noProxySpecification);
- for (String specification : noProxySpecifications){
+ for (String specification : noProxySpecifications) {
specification = stripLeadingStarDot(stripLeadingDot(specification.trim()));
- if (specification.isEmpty() ) {
+ if (specification.isEmpty()) {
continue;
}
if (isIpAddress(specification)) {
@@ -149,12 +148,10 @@ private boolean matchesSubnet(String host) {
}
private boolean matchesDomainHost(String host) {
- return noProxyDomainsHosts.stream().
- anyMatch(host::endsWith);
+ return noProxyDomainsHosts.stream().anyMatch(host::endsWith);
}
private boolean isIpAddress(String host) {
return InetAddressValidator.getInstance().isValid(host);
}
-
}
diff --git a/src/main/java/hudson/remoting/ObjectInputStreamEx.java b/src/main/java/hudson/remoting/ObjectInputStreamEx.java
index 4a0070cf6..e1d4ef482 100644
--- a/src/main/java/hudson/remoting/ObjectInputStreamEx.java
+++ b/src/main/java/hudson/remoting/ObjectInputStreamEx.java
@@ -43,7 +43,7 @@ public class ObjectInputStreamEx extends ObjectInputStream {
*/
@Deprecated
public ObjectInputStreamEx(InputStream in, ClassLoader cl) throws IOException {
- this(in,cl,ClassFilter.DEFAULT);
+ this(in, cl, ClassFilter.DEFAULT);
}
public ObjectInputStreamEx(InputStream in, ClassLoader cl, ClassFilter filter) throws IOException {
@@ -78,8 +78,7 @@ protected Class> resolveProxyClass(String[] interfaces) throws IOException, Cl
if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
if (hasNonPublicInterface) {
if (nonPublicLoader != cl.getClassLoader()) {
- throw new IllegalAccessError(
- "conflicting non-public interface class loaders");
+ throw new IllegalAccessError("conflicting non-public interface class loaders");
}
} else {
nonPublicLoader = cl.getClassLoader();
@@ -89,9 +88,7 @@ protected Class> resolveProxyClass(String[] interfaces) throws IOException, Cl
classObjs[i] = cl;
}
try {
- return Proxy.getProxyClass(
- hasNonPublicInterface ? nonPublicLoader : latestLoader,
- classObjs);
+ return Proxy.getProxyClass(hasNonPublicInterface ? nonPublicLoader : latestLoader, classObjs);
} catch (IllegalArgumentException e) {
throw new ClassNotFoundException(null, e);
}
@@ -99,7 +96,7 @@ protected Class> resolveProxyClass(String[] interfaces) throws IOException, Cl
@Override
protected Object resolveObject(Object obj) throws IOException {
- if(obj instanceof URL){
+ if (obj instanceof URL) {
// SECURITY-637, URL deserialization could lead to DNS query
return URLDeserializationHelper.wrapIfRequired((URL) obj);
}
diff --git a/src/main/java/hudson/remoting/PingThread.java b/src/main/java/hudson/remoting/PingThread.java
index b5373694c..08008588a 100644
--- a/src/main/java/hudson/remoting/PingThread.java
+++ b/src/main/java/hudson/remoting/PingThread.java
@@ -59,7 +59,7 @@ public abstract class PingThread extends Thread {
private final long interval;
public PingThread(Channel channel, long timeout, long interval) {
- super("Ping thread for channel "+channel);
+ super("Ping thread for channel " + channel);
this.channel = channel;
this.timeout = timeout;
this.interval = interval;
@@ -81,24 +81,24 @@ public PingThread(Channel channel) {
@Override
public void run() {
try {
- while(true) {
+ while (true) {
long nextCheck = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(interval);
ping();
// wait until the next check
long diff;
- while((diff = nextCheck - System.nanoTime()) > 0) {
+ while ((diff = nextCheck - System.nanoTime()) > 0) {
TimeUnit.NANOSECONDS.sleep(diff);
}
}
} catch (ChannelClosedException e) {
- LOGGER.fine(getName()+" is closed. Terminating");
+ LOGGER.fine(getName() + " is closed. Terminating");
} catch (IOException e) {
onDead(e);
} catch (InterruptedException e) {
// use interruption as a way to terminate the ping thread.
- LOGGER.fine(getName()+" is interrupted. Terminating");
+ LOGGER.fine(getName() + " is interrupted. Terminating");
}
}
@@ -111,14 +111,17 @@ private void ping() throws IOException, InterruptedException {
long remaining = end - System.nanoTime();
do {
- LOGGER.log(Level.FINE, "waiting {0}s on {1}", new Object[] {TimeUnit.NANOSECONDS.toSeconds(remaining), channel.getName()});
+ LOGGER.log(Level.FINE, "waiting {0}s on {1}", new Object[] {
+ TimeUnit.NANOSECONDS.toSeconds(remaining), channel.getName()
+ });
try {
- f.get(Math.max(1,remaining),TimeUnit.NANOSECONDS);
+ f.get(Math.max(1, remaining), TimeUnit.NANOSECONDS);
LOGGER.log(Level.FINE, "ping succeeded on {0}", channel.getName());
return;
} catch (ExecutionException e) {
- if (e.getCause() instanceof RequestAbortedException)
+ if (e.getCause() instanceof RequestAbortedException) {
return; // connection has shut down orderly.
+ }
onDead(e);
return;
} catch (TimeoutException e) {
@@ -126,9 +129,10 @@ private void ping() throws IOException, InterruptedException {
// so let's make sure that it really waited enough
}
remaining = end - System.nanoTime();
- } while(remaining>0);
+ } while (remaining > 0);
- onDead(new TimeoutException("Ping started at "+start+" hasn't completed by "+System.currentTimeMillis()));//.initCause(e)
+ onDead(new TimeoutException(
+ "Ping started at " + start + " hasn't completed by " + System.currentTimeMillis())); // .initCause(e)
}
/**
@@ -147,7 +151,7 @@ private void ping() throws IOException, InterruptedException {
* @since 2.9
*/
protected void onDead(Throwable diagnosis) {
- onDead(); // fall back
+ onDead(); // fall back
}
private static final class Ping implements InternalCallable {
diff --git a/src/main/java/hudson/remoting/Pipe.java b/src/main/java/hudson/remoting/Pipe.java
index f327099b5..0e3f1420d 100644
--- a/src/main/java/hudson/remoting/Pipe.java
+++ b/src/main/java/hudson/remoting/Pipe.java
@@ -1,18 +1,18 @@
/*
* The MIT License
- *
+ *
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -140,14 +140,14 @@ public void error(Throwable t) throws IOException {
*/
public static Pipe createRemoteToLocal() {
// OutputStream will be created on the target
- return new Pipe(new FastPipedInputStream(),null);
+ return new Pipe(new FastPipedInputStream(), null);
}
/**
* Creates a {@link Pipe} that allows local system to write and remote system to read.
*/
public static Pipe createLocalToRemote() {
- return new Pipe(null,new ProxyOutputStream());
+ return new Pipe(null, new ProxyOutputStream());
}
private void writeObject(ObjectOutputStream oos) throws IOException {
@@ -157,10 +157,11 @@ private void writeObject(ObjectOutputStream oos) throws IOException {
// The former uses 1M, while the latter uses 64K, so if the sender is too fast, it'll cause
// the pipe IO thread to block other IO activities. Fix this by first using adaptive growing buffer
// in FastPipedInputStream, then make sure the maximum size is bigger than the pipe window size.
- if(in!=null && out==null) {
+ if (in != null && out == null) {
// remote will write to local
- FastPipedOutputStream pos = new FastPipedOutputStream((FastPipedInputStream)in);
- int oid = ch.internalExport(Object.class, pos, false); // this export is unexported in ProxyOutputStream.finalize()
+ FastPipedOutputStream pos = new FastPipedOutputStream((FastPipedInputStream) in);
+ int oid = ch.internalExport(
+ Object.class, pos, false); // this export is unexported in ProxyOutputStream.finalize()
oos.writeBoolean(true); // marker
oos.writeInt(oid);
@@ -174,11 +175,13 @@ private void writeObject(ObjectOutputStream oos) throws IOException {
}
}
- @SuppressFBWarnings(value = "DESERIALIZATION_GADGET", justification = "Serializable only over remoting. Class filtering is done through JEP-200.")
+ @SuppressFBWarnings(
+ value = "DESERIALIZATION_GADGET",
+ justification = "Serializable only over remoting. Class filtering is done through JEP-200.")
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
final Channel channel = getChannelForSerialization();
- if(ois.readBoolean()) {
+ if (ois.readBoolean()) {
// local will write to remote
in = null;
out = new ProxyOutputStream(channel, ois.readInt());
@@ -192,7 +195,8 @@ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFound
// we want 'oidRos' to send data to this PipedOutputStream
FastPipedOutputStream pos = new FastPipedOutputStream();
FastPipedInputStream pis = new FastPipedInputStream(pos);
- final int oidPos = channel.internalExport(Object.class, pos, false); // this gets unexported when the remote ProxyOutputStream closes.
+ final int oidPos = channel.internalExport(
+ Object.class, pos, false); // this gets unexported when the remote ProxyOutputStream closes.
// tell 'ros' to connect to our 'pos'.
channel.send(new ConnectCommand(oidRos, oidPos));
@@ -221,11 +225,11 @@ protected void execute(final Channel channel) throws ExecutionException {
channel.pipeWriter.submit(0, () -> {
try {
final ProxyOutputStream ros = (ProxyOutputStream) channel.getExportedObject(oidRos);
- channel.unexport(oidRos,createdAt);
+ channel.unexport(oidRos, createdAt);
// the above unexport cancels out the export in writeObject above
ros.connect(channel, oidPos);
} catch (IOException e) {
- logger.log(Level.SEVERE,"Failed to connect to pipe",e);
+ logger.log(Level.SEVERE, "Failed to connect to pipe", e);
} catch (ExecutionException ex) {
throw new IllegalStateException(ex);
}
diff --git a/src/main/java/hudson/remoting/PipeWindow.java b/src/main/java/hudson/remoting/PipeWindow.java
index e00c8459c..891d19bce 100644
--- a/src/main/java/hudson/remoting/PipeWindow.java
+++ b/src/main/java/hudson/remoting/PipeWindow.java
@@ -105,7 +105,7 @@ abstract class PipeWindow {
*/
void dead(@CheckForNull Throwable cause) {
// We need to record
- this.dead = cause != null ? cause : new RemotingSystemException("Unknown cause", null) ;
+ this.dead = cause != null ? cause : new RemotingSystemException("Unknown cause", null);
}
/**
@@ -120,7 +120,6 @@ protected void checkDeath() throws IOException {
}
}
-
/**
* Fake implementation used when the receiver side doesn't support throttling.
*/
@@ -131,8 +130,7 @@ int max() {
}
@Override
- void increase(int delta) {
- }
+ void increase(int delta) {}
@Override
int peek() {
@@ -146,8 +144,7 @@ int get(int min) throws InterruptedException, IOException {
}
@Override
- void decrease(int delta) {
- }
+ void decrease(int delta) {}
}
static final class Key {
@@ -159,7 +156,9 @@ static final class Key {
@Override
public boolean equals(Object o) {
- if (o == null || getClass() != o.getClass()) return false;
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
return oid == ((Key) o).oid;
}
@@ -170,7 +169,7 @@ public int hashCode() {
}
}
- //TODO: Consider rework and cleanup of the fields
+ // TODO: Consider rework and cleanup of the fields
@SuppressFBWarnings(value = "URF_UNREAD_FIELD", justification = "Legacy implementation")
static class Real extends PipeWindow {
private final int initial;
@@ -183,6 +182,7 @@ static class Real extends PipeWindow {
* Total bytes that the remote side acked.
*/
private long acked;
+
private final int oid;
/**
* The only strong reference to the key, which in turn
@@ -204,8 +204,9 @@ int max() {
@Override
public synchronized void increase(int delta) {
- if (LOGGER.isLoggable(Level.FINER))
- LOGGER.finer(String.format("increase(%d,%d)->%d",oid,delta,delta+available));
+ if (LOGGER.isLoggable(Level.FINER)) {
+ LOGGER.finer(String.format("increase(%d,%d)->%d", oid, delta, delta + available));
+ }
available += delta;
acked += delta;
notifyAll();
@@ -223,10 +224,11 @@ public synchronized int peek() {
public int get(int min) throws InterruptedException, IOException {
checkDeath();
synchronized (this) {
- if (available>=min)
+ if (available >= min) {
return available;
+ }
- while (available%d",oid,delta,available-delta));
+ if (LOGGER.isLoggable(Level.FINER)) {
+ LOGGER.finer(String.format("decrease(%d,%d)->%d", oid, delta, available - delta));
+ }
available -= delta;
- written+= delta;
+ written += delta;
/*
HUDSON-7745 says the following assertion fails, which AFAICT is only possible if multiple
threads write to OutputStream concurrently, but that doesn't happen in most of the situations, so
@@ -248,8 +251,8 @@ public synchronized void decrease(int delta) {
HUDSON-7581 appears to be related.
*/
-// if (available<0)
-// throw new AssertionError();
+ // if (available<0)
+ // throw new AssertionError();
}
}
diff --git a/src/main/java/hudson/remoting/PipeWriter.java b/src/main/java/hudson/remoting/PipeWriter.java
index afb03d9e5..5d6cbbca5 100644
--- a/src/main/java/hudson/remoting/PipeWriter.java
+++ b/src/main/java/hudson/remoting/PipeWriter.java
@@ -105,13 +105,14 @@ public synchronized Future> set(Future> f) {
}
public synchronized Future> get() throws InterruptedException {
- while (f==null)
+ while (f == null) {
wait();
+ }
return f;
}
}
- private final Map pendingIO = Collections.synchronizedMap(new HashMap<>());
+ private final Map pendingIO = Collections.synchronizedMap(new HashMap<>());
/**
* Actually carries out the {@link Runnable}s.
@@ -138,8 +139,9 @@ public void shutdown() {
* Future object that can be used to wait for the completion of the submitted I/O task.
*/
public Future> submit(final int id, final Runnable command) {
- if (id==0)
+ if (id == 0) {
return base.submit(command);
+ }
// this indirection is needed to ensure that put happens before remove
// if we store Future itself, then remove can happen before put, and
@@ -147,7 +149,7 @@ public Future> submit(final int id, final Runnable command) {
FutureHolder fh = new FutureHolder();
FutureHolder old = pendingIO.put(id, fh);
- assert old==null;
+ assert old == null;
return fh.set(base.submit(new Runnable() {
@Override
@@ -155,11 +157,11 @@ public void run() {
final Thread t = Thread.currentThread();
final String oldName = t.getName();
try {
- t.setName(oldName+" : IO ID="+id+" : seq#="+iota.getAndIncrement());
+ t.setName(oldName + " : IO ID=" + id + " : seq#=" + iota.getAndIncrement());
command.run();
} finally {
FutureHolder old = pendingIO.remove(id);
- assert old!=null;
+ assert old != null;
t.setName(oldName);
}
}
@@ -180,7 +182,9 @@ public void run() {
*/
public Future> get(int id) throws InterruptedException {
FutureHolder f = pendingIO.get(id);
- if (f==null) return SIGNALED; // already completed
+ if (f == null) {
+ return SIGNALED; // already completed
+ }
return f.get();
}
diff --git a/src/main/java/hudson/remoting/PreloadJarTask.java b/src/main/java/hudson/remoting/PreloadJarTask.java
index bfad994a2..3169973ae 100644
--- a/src/main/java/hudson/remoting/PreloadJarTask.java
+++ b/src/main/java/hudson/remoting/PreloadJarTask.java
@@ -34,13 +34,14 @@
*
* @author Kohsuke Kawaguchi
*/
-final class PreloadJarTask implements DelegatingCallable {
+final class PreloadJarTask implements DelegatingCallable {
/**
* Jar file to be preloaded.
*/
private final URL[] jars;
- //TODO: This implementation exists starting from https://github.com/jenkinsci/remoting/commit/f3d0a81fdf46a10c3c6193faf252efaeaee98823
+ // TODO: This implementation exists starting from
+ // https://github.com/jenkinsci/remoting/commit/f3d0a81fdf46a10c3c6193faf252efaeaee98823
// Since this time nothing has blown up, but it still seems to be suspicious.
// The solution for null classloaders is available in RemoteDiagnostics.Script#call() in the Jenkins core codebase
@CheckForNull
@@ -59,13 +60,15 @@ public ClassLoader getClassLoader() {
@Override
public Boolean call() throws IOException {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
- if (!(cl instanceof RemoteClassLoader))
+ if (!(cl instanceof RemoteClassLoader)) {
return false;
+ }
RemoteClassLoader rcl = (RemoteClassLoader) cl;
boolean r = false;
- for (URL jar : jars)
+ for (URL jar : jars) {
r |= rcl.prefetch(jar);
+ }
return r;
}
@@ -75,7 +78,7 @@ public Boolean call() throws IOException {
*/
@Override
public void checkRoles(RoleChecker checker) throws SecurityException {
- checker.check(this,Role.UNKNOWN);
+ checker.check(this, Role.UNKNOWN);
}
private static final long serialVersionUID = -773448303394727271L;
diff --git a/src/main/java/hudson/remoting/ProxyException.java b/src/main/java/hudson/remoting/ProxyException.java
index 6dd6b781d..38680a279 100644
--- a/src/main/java/hudson/remoting/ProxyException.java
+++ b/src/main/java/hudson/remoting/ProxyException.java
@@ -1,18 +1,18 @@
/*
* The MIT License
- *
+ *
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -65,6 +65,6 @@ private ProxyException(@NonNull Throwable cause, @NonNull Set visited
*/
@Override
public ProxyException getCause() {
- return (ProxyException)super.getCause();
+ return (ProxyException) super.getCause();
}
}
diff --git a/src/main/java/hudson/remoting/ProxyInputStream.java b/src/main/java/hudson/remoting/ProxyInputStream.java
index 005e9ce06..e9fc26f57 100644
--- a/src/main/java/hudson/remoting/ProxyInputStream.java
+++ b/src/main/java/hudson/remoting/ProxyInputStream.java
@@ -1,18 +1,18 @@
/*
* The MIT License
- *
+ *
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -43,12 +43,12 @@
* @author Kohsuke Kawaguchi
*/
final class ProxyInputStream extends InputStream {
-
+
private static final Logger LOGGER = Logger.getLogger(ProxyInputStream.class.getName());
-
+
private Channel channel;
private int oid;
-
+
/**
* Creates an already connected {@link ProxyOutputStream}.
*
@@ -64,12 +64,13 @@ public ProxyInputStream(Channel channel, int oid) throws IOException {
public int read() throws IOException {
try {
Buffer buf = _read(1);
- if(buf.len==1)
+ if (buf.len == 1) {
// byte->int expansion needs to be done carefully becaue byte in Java is signed
// whose idea was it to make byte signed, anyway!?
- return ((int)buf.buf[0])&0xFF;
- else
+ return ((int) buf.buf[0]) & 0xFF;
+ } else {
return -1;
+ }
} catch (InterruptedException e) {
// pretend EOF
Thread.currentThread().interrupt(); // process interrupt later
@@ -86,8 +87,10 @@ private synchronized Buffer _read(int len) throws IOException, InterruptedExcept
public int read(@NonNull byte[] b, int off, int len) throws IOException {
try {
Buffer buf = _read(len);
- if(buf.len==-1) return -1;
- System.arraycopy(buf.buf,0,b,off,buf.len);
+ if (buf.len == -1) {
+ return -1;
+ }
+ System.arraycopy(buf.buf, 0, b, off, buf.len);
return buf.len;
} catch (InterruptedException e) {
// pretend EOF
@@ -99,7 +102,7 @@ public int read(@NonNull byte[] b, int off, int len) throws IOException {
@Override
public synchronized void close() throws IOException {
- if(channel!=null) {
+ if (channel != null) {
channel.send(new EOF(oid));
channel = null;
oid = -1;
@@ -115,7 +118,7 @@ public Buffer(int len) {
}
public void read(InputStream in) throws IOException {
- len = in.read(buf,0,buf.length);
+ len = in.read(buf, 0, buf.length);
}
private static final long serialVersionUID = 1L;
@@ -124,7 +127,7 @@ public void read(InputStream in) throws IOException {
/**
* Command to fetch bytes.
*/
- private static final class Chunk extends Request {
+ private static final class Chunk extends Request {
private final int oid;
private final int len;
@@ -153,7 +156,6 @@ public String toString() {
}
private static final long serialVersionUID = 1L;
-
}
/**
@@ -169,19 +171,19 @@ public EOF(int oid) {
@Override
protected void execute(Channel channel) {
final InputStream in = (InputStream) channel.getExportedObjectOrNull(oid);
- // EOF may be late to the party if we interrupt request, hence we do not fail for this command
+ // EOF may be late to the party if we interrupt request, hence we do not fail for this command
if (in == null) { // Input stream has not been closed yet
LOGGER.log(Level.FINE, "InputStream with oid=%s has been already unexported", oid);
return;
}
-
- channel.unexport(oid,createdAt,false);
+
+ channel.unexport(oid, createdAt, false);
IOUtils.closeQuietly(in);
}
@Override
public String toString() {
- return "ProxyInputStream.EOF("+oid+")";
+ return "ProxyInputStream.EOF(" + oid + ")";
}
private static final long serialVersionUID = 1L;
diff --git a/src/main/java/hudson/remoting/ProxyOutputStream.java b/src/main/java/hudson/remoting/ProxyOutputStream.java
index db0b70070..9e351ec55 100644
--- a/src/main/java/hudson/remoting/ProxyOutputStream.java
+++ b/src/main/java/hudson/remoting/ProxyOutputStream.java
@@ -1,18 +1,18 @@
/*
* The MIT License
- *
+ *
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -58,8 +58,7 @@ final class ProxyOutputStream extends OutputStream implements ErrorPropagatingOu
* when it's {@link #connect(Channel,int) connected} later,
* the data will be sent at once to the remote stream.
*/
- public ProxyOutputStream() {
- }
+ public ProxyOutputStream() {}
/**
* Creates an already connected {@link ProxyOutputStream}.
@@ -68,87 +67,91 @@ public ProxyOutputStream() {
* The object id of the exported {@link OutputStream}.
*/
public ProxyOutputStream(@NonNull Channel channel, int oid) throws IOException {
- connect(channel,oid);
+ connect(channel, oid);
}
/**
* Connects this stream to the specified remote object.
*/
synchronized void connect(@NonNull Channel channel, int oid) throws IOException {
- if(this.channel!=null)
+ if (this.channel != null) {
throw new IllegalStateException("Cannot connect twice");
- if(oid==0)
+ }
+ if (oid == 0) {
throw new IllegalArgumentException("oid=0");
+ }
this.channel = channel;
this.oid = oid;
- window = channel.getPipeWindow(oid);
+ window = channel.getPipeWindow(oid);
- if(closed) // already marked closed?
+ if (closed) { // already marked closed?
doClose(error);
+ }
notifyAll(); // release blocking writes
}
@Override
public void write(int b) throws IOException {
- write(new byte[]{(byte)b},0,1);
+ write(new byte[] {(byte) b}, 0, 1);
}
@Override
public synchronized void write(@NonNull byte[] b, int off, int len) throws IOException {
try {
// block until stream gets connected
- while (channel==null) {
- if(closed)
+ while (channel == null) {
+ if (closed) {
throw new IOException("stream is already closed");
+ }
wait();
}
final int max = window.max();
- while (len>0) {
+ while (len > 0) {
/*
- To avoid fragmentation of the pipe window, at least demand that 10% of the pipe window
- be reclaimed.
+ To avoid fragmentation of the pipe window, at least demand that 10% of the pipe window
+ be reclaimed.
- Imagine a large latency network where we are always low on the window size,
- and we are continuously sending data of irregular size. In such a circumstance,
- a fragmentation will happen. We start sending out a small Chunk at a time (say 4 bytes),
- and when its Ack comes back, it gets immediately consumed by another out-bound Chunk of 4 bytes.
+ Imagine a large latency network where we are always low on the window size,
+ and we are continuously sending data of irregular size. In such a circumstance,
+ a fragmentation will happen. We start sending out a small Chunk at a time (say 4 bytes),
+ and when its Ack comes back, it gets immediately consumed by another out-bound Chunk of 4 bytes.
- Clearly, it's better to wait a bit until we have a sizable pipe window, then send out
- a bigger Chunk, since Chunks have static overheads. This code does just that.
+ Clearly, it's better to wait a bit until we have a sizable pipe window, then send out
+ a bigger Chunk, since Chunks have static overheads. This code does just that.
- (Except when what we are trying to send as a whole is smaller than the current available
- window size, in which case there's no point in waiting.)
- */
- int sendable = Math.min(window.get(Math.min(max/10,len)),len);
+ (Except when what we are trying to send as a whole is smaller than the current available
+ window size, in which case there's no point in waiting.)
+ */
+ int sendable = Math.min(window.get(Math.min(max / 10, len)), len);
/*
- Imagine if we have a lot of data to send and the pipe window is fully available.
- If we create one Chunk that fully uses the window size, we need to wait for the
- whole Chunk to get to the other side, then the Ack to come back to this side,
- before we can send a next Chunk. While the Ack is traveling back to us, we have
- to sit idle. This fails to utilize available bandwidth.
-
- A better strategy is to create a smaller Chunk, say half the window size.
- This allows the other side to send back the ack while we are sending the second
- Chunk. In a network with a non-trivial latency, this allows Chunk and Ack
- to overlap, and that improves the utilization.
-
- It's not clear what the best size of the chunk to send (there's a certain
- overhead in our Command structure, around 100-200 bytes), so I'm just starting
- with 2. Further analysis would be needed to determine the best value.
- */
- sendable = Math.min(sendable, max /2);
-
- channel.send(new Chunk(channel.newIoId(),oid,b,off,sendable));
+ Imagine if we have a lot of data to send and the pipe window is fully available.
+ If we create one Chunk that fully uses the window size, we need to wait for the
+ whole Chunk to get to the other side, then the Ack to come back to this side,
+ before we can send a next Chunk. While the Ack is traveling back to us, we have
+ to sit idle. This fails to utilize available bandwidth.
+
+ A better strategy is to create a smaller Chunk, say half the window size.
+ This allows the other side to send back the ack while we are sending the second
+ Chunk. In a network with a non-trivial latency, this allows Chunk and Ack
+ to overlap, and that improves the utilization.
+
+ It's not clear what the best size of the chunk to send (there's a certain
+ overhead in our Command structure, around 100-200 bytes), so I'm just starting
+ with 2. Further analysis would be needed to determine the best value.
+ */
+ sendable = Math.min(sendable, max / 2);
+
+ channel.send(new Chunk(channel.newIoId(), oid, b, off, sendable));
window.decrease(sendable);
- off+=sendable;
- len-=sendable;
+ off += sendable;
+ len -= sendable;
}
} catch (InterruptedException e) {
- throw (IOException)new InterruptedIOException().initCause(e);
+ throw (IOException) new InterruptedIOException().initCause(e);
}
}
@@ -170,13 +173,14 @@ public synchronized void error(Throwable e) throws IOException {
closed = true;
error = e;
}
- if(channel!=null)
+ if (channel != null) {
doClose(e);
- notifyAll(); // unblock any pending write
+ }
+ notifyAll(); // unblock any pending write
}
private void doClose(Throwable error) throws IOException {
- channel.send(new EOF(channel.newIoId(),oid,error));
+ channel.send(new EOF(channel.newIoId(), oid, error));
channel = null;
oid = -1;
}
@@ -186,8 +190,8 @@ protected void finalize() throws Throwable {
super.finalize();
// if we haven't done so, release the exported object on the remote side.
// if the object is auto-unexported, the export entry could have already been removed.
- if(channel != null && oid != -1) {
- channel.send(new Unexport(channel.newIoId(),oid));
+ if (channel != null && oid != -1) {
+ channel.send(new Unexport(channel.newIoId(), oid));
oid = -1;
}
}
@@ -213,12 +217,13 @@ protected void finalize() throws Throwable {
*/
@Deprecated
private static void markForIoSync(Channel channel, int requestId, java.util.concurrent.Future> ioOp) {
- Request,?> call = channel.pendingCalls.get(requestId);
+ Request, ?> call = channel.pendingCalls.get(requestId);
// call==null if:
// 1) the remote peer uses old version that doesn't set the requestId field
// 2) a bug in the code, but in that case we are being defensive
- if (call!=null)
+ if (call != null) {
call.lastIo = ioOp;
+ }
}
/**
@@ -237,11 +242,11 @@ public Chunk(int ioId, int oid, byte[] buf, int start, int len) {
super(false);
this.ioId = ioId;
this.oid = oid;
- if (start==0 && len==buf.length)
+ if (start == 0 && len == buf.length) {
this.buf = buf;
- else {
+ } else {
this.buf = new byte[len];
- System.arraycopy(buf,start,this.buf,0,len);
+ System.arraycopy(buf, start, this.buf, 0, len);
}
}
@@ -251,33 +256,36 @@ protected void execute(final Channel channel) throws ExecutionException {
try {
os = (OutputStream) channel.getExportedObject(oid);
} catch (ExecutionException ex) {
- throw new ExecutionException(String.format("Channel %s: Output stream object has been released before sending last chunk for oid=%s",
- channel.getName(), oid), ex);
+ throw new ExecutionException(
+ String.format(
+ "Channel %s: Output stream object has been released before sending last chunk for oid=%s",
+ channel.getName(), oid),
+ ex);
}
- markForIoSync(channel,requestId,channel.pipeWriter.submit(ioId, () -> {
+ markForIoSync(channel, requestId, channel.pipeWriter.submit(ioId, () -> {
try {
os.write(buf);
} catch (IOException e) {
try {
- channel.send(new NotifyDeadWriter(channel,e,oid));
+ channel.send(new NotifyDeadWriter(channel, e, oid));
} catch (ChannelClosedException x) {
// the other direction can be already closed if the connection
// shut down is initiated from this side. In that case, remain silent.
} catch (IOException x) {
// ignore errors
- LOGGER.log(Level.WARNING, "Failed to notify the sender that the write end is dead",x);
- LOGGER.log(Level.WARNING, "... the failed write was:",e);
+ LOGGER.log(Level.WARNING, "Failed to notify the sender that the write end is dead", x);
+ LOGGER.log(Level.WARNING, "... the failed write was:", e);
}
} finally {
if (channel.remoteCapability.supportsPipeThrottling()) {
try {
- channel.send(new Ack(oid,buf.length));
+ channel.send(new Ack(oid, buf.length));
} catch (ChannelClosedException x) {
// the other direction can be already closed if the connection
// shut down is initiated from this side. In that case, remain silent.
} catch (IOException e) {
// ignore errors
- LOGGER.log(Level.WARNING, "Failed to ack the stream",e);
+ LOGGER.log(Level.WARNING, "Failed to ack the stream", e);
}
}
}
@@ -286,7 +294,7 @@ protected void execute(final Channel channel) throws ExecutionException {
@Override
public String toString() {
- return "Pipe.Chunk("+oid+","+buf.length+")";
+ return "Pipe.Chunk(" + oid + "," + buf.length + ")";
}
private static final long serialVersionUID = 1L;
@@ -309,7 +317,7 @@ public Flush(int ioId, int oid) {
@Override
protected void execute(Channel channel) throws ExecutionException {
final OutputStream os = (OutputStream) channel.getExportedObject(oid);
- markForIoSync(channel,requestId,channel.pipeWriter.submit(ioId, () -> {
+ markForIoSync(channel, requestId, channel.pipeWriter.submit(ioId, () -> {
try {
os.flush();
} catch (IOException e) {
@@ -320,7 +328,7 @@ protected void execute(Channel channel) throws ExecutionException {
@Override
public String toString() {
- return "Pipe.Flush("+oid+")";
+ return "Pipe.Flush(" + oid + ")";
}
private static final long serialVersionUID = 1L;
@@ -343,12 +351,12 @@ public Unexport(int ioId, int oid) {
@Override
protected void execute(final Channel channel) {
- channel.pipeWriter.submit(ioId, () -> channel.unexport(oid,createdAt,false));
+ channel.pipeWriter.submit(ioId, () -> channel.unexport(oid, createdAt, false));
}
@Override
public String toString() {
- return "ProxyOutputStream.Unexport("+oid+")";
+ return "ProxyOutputStream.Unexport(" + oid + ")";
}
private static final long serialVersionUID = 1L;
@@ -369,7 +377,6 @@ public EOF(int ioId, int oid, Throwable error) {
this.error = error;
}
-
@Override
protected void execute(final Channel channel) {
final OutputStream os = (OutputStream) channel.getExportedObjectOrNull(oid);
@@ -378,11 +385,12 @@ protected void execute(final Channel channel) {
LOGGER.log(Level.FINE, "InputStream with oid=%s has been already unexported", oid);
return;
}
- markForIoSync(channel,requestId,channel.pipeWriter.submit(ioId, () -> {
- channel.unexport(oid,createdAt,false);
+ markForIoSync(channel, requestId, channel.pipeWriter.submit(ioId, () -> {
+ channel.unexport(oid, createdAt, false);
try {
- if (error!=null && os instanceof ErrorPropagatingOutputStream)
+ if (error != null && os instanceof ErrorPropagatingOutputStream) {
((ErrorPropagatingOutputStream) os).error(error);
+ }
os.close();
} catch (IOException e) {
// ignore errors
@@ -392,7 +400,7 @@ protected void execute(final Channel channel) {
@Override
public String toString() {
- return "ProxyOutputStream.EOF("+oid+")";
+ return "ProxyOutputStream.EOF(" + oid + ")";
}
private static final long serialVersionUID = 1L;
@@ -425,7 +433,7 @@ protected void execute(Channel channel) {
@Override
public String toString() {
- return "ProxyOutputStream.Ack("+oid+','+size+")";
+ return "ProxyOutputStream.Ack(" + oid + ',' + size + ")";
}
private static final long serialVersionUID = 1L;
@@ -437,8 +445,8 @@ public String toString() {
private static final class NotifyDeadWriter extends Command {
private final int oid;
- private NotifyDeadWriter(Channel channel,Throwable cause, int oid) {
- super(channel,cause);
+ private NotifyDeadWriter(Channel channel, Throwable cause, int oid) {
+ super(channel, cause);
this.oid = oid;
}
@@ -450,7 +458,7 @@ protected void execute(Channel channel) {
@Override
public String toString() {
- return "ProxyOutputStream.Dead("+oid+")";
+ return "ProxyOutputStream.Dead(" + oid + ")";
}
private static final long serialVersionUID = 1L;
diff --git a/src/main/java/hudson/remoting/ProxyWriter.java b/src/main/java/hudson/remoting/ProxyWriter.java
index e7d6c68f5..2da94fb51 100644
--- a/src/main/java/hudson/remoting/ProxyWriter.java
+++ b/src/main/java/hudson/remoting/ProxyWriter.java
@@ -1,18 +1,18 @@
/*
* The MIT License
- *
+ *
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -40,9 +40,10 @@
* {@link Writer} on a remote machine.
*/
final class ProxyWriter extends Writer {
-
+
@GuardedBy("this")
private Channel channel;
+
private int oid;
private PipeWindow window;
@@ -72,36 +73,38 @@ final class ProxyWriter extends Writer {
* The object id of the exported {@link Writer}.
*/
public ProxyWriter(@NonNull Channel channel, int oid) throws IOException {
- connect(channel,oid);
+ connect(channel, oid);
}
/**
* Connects this stream to the specified remote object.
*/
synchronized void connect(@NonNull Channel channel, int oid) throws IOException {
- if(this.channel!=null)
+ if (this.channel != null) {
throw new IllegalStateException("Cannot connect twice");
- if(oid==0)
+ }
+ if (oid == 0) {
throw new IllegalArgumentException("oid=0");
+ }
this.channel = channel;
this.oid = oid;
- window = channel.getPipeWindow(oid);
+ window = channel.getPipeWindow(oid);
// if we already have bytes to write, do so now.
- if(tmp!=null) {
+ if (tmp != null) {
char[] b = tmp.toCharArray();
tmp = null;
_write(b, 0, b.length);
}
- if(closeCause != null) { // already closed asynchronously?
+ if (closeCause != null) { // already closed asynchronously?
close();
}
}
@Override
public void write(int c) throws IOException {
- write(new char[]{(char)c},0,1);
+ write(new char[] {(char) c}, 0, 1);
}
@Override
@@ -116,65 +119,67 @@ public void write(@NonNull char[] cbuf, int off, int len) throws IOException {
* {@link #write(char[])} without the close check.
*/
private synchronized void _write(char[] cbuf, int off, int len) throws IOException {
- if(channel==null) {
- if(tmp==null)
+ if (channel == null) {
+ if (tmp == null) {
tmp = new CharArrayWriter();
+ }
tmp.write(cbuf);
} else {
final int max = window.max();
- while (len>0) {
+ while (len > 0) {
int sendable;
try {
/*
- To avoid fragmentation of the pipe window, at least demand that 10% of the pipe window
- be reclaimed.
+ To avoid fragmentation of the pipe window, at least demand that 10% of the pipe window
+ be reclaimed.
- Imagine a large latency network where we are always low on the window size,
- and we are continuously sending data of irregular size. In such a circumstance,
- a fragmentation will happen. We start sending out a small Chunk at a time (say 4 bytes),
- and when its Ack comes back, it gets immediately consumed by another out-bound Chunk of 4 bytes.
+ Imagine a large latency network where we are always low on the window size,
+ and we are continuously sending data of irregular size. In such a circumstance,
+ a fragmentation will happen. We start sending out a small Chunk at a time (say 4 bytes),
+ and when its Ack comes back, it gets immediately consumed by another out-bound Chunk of 4 bytes.
- Clearly, it's better to wait a bit until we have a sizable pipe window, then send out
- a bigger Chunk, since Chunks have static overheads. This code does just that.
+ Clearly, it's better to wait a bit until we have a sizable pipe window, then send out
+ a bigger Chunk, since Chunks have static overheads. This code does just that.
- (Except when what we are trying to send as a whole is smaller than the current available
- window size, in which case there's no point in waiting.)
- */
- sendable = Math.min(window.get(Math.min(max/10,len)),len);
+ (Except when what we are trying to send as a whole is smaller than the current available
+ window size, in which case there's no point in waiting.)
+ */
+ sendable = Math.min(window.get(Math.min(max / 10, len)), len);
/*
- Imagine if we have a lot of data to send and the pipe window is fully available.
- If we create one Chunk that fully uses the window size, we need to wait for the
- whole Chunk to get to the other side, then the Ack to come back to this side,
- before we can send a next Chunk. While the Ack is traveling back to us, we have
- to sit idle. This fails to utilize available bandwidth.
-
- A better strategy is to create a smaller Chunk, say half the window size.
- This allows the other side to send back the ack while we are sending the second
- Chunk. In a network with a non-trivial latency, this allows Chunk and Ack
- to overlap, and that improves the utilization.
-
- It's not clear what the best size of the chunk to send (there's a certain
- overhead in our Command structure, around 100-200 bytes), so I'm just starting
- with 2. Further analysis would be needed to determine the best value.
- */
- sendable = Math.min(sendable, max /2);
+ Imagine if we have a lot of data to send and the pipe window is fully available.
+ If we create one Chunk that fully uses the window size, we need to wait for the
+ whole Chunk to get to the other side, then the Ack to come back to this side,
+ before we can send a next Chunk. While the Ack is traveling back to us, we have
+ to sit idle. This fails to utilize available bandwidth.
+
+ A better strategy is to create a smaller Chunk, say half the window size.
+ This allows the other side to send back the ack while we are sending the second
+ Chunk. In a network with a non-trivial latency, this allows Chunk and Ack
+ to overlap, and that improves the utilization.
+
+ It's not clear what the best size of the chunk to send (there's a certain
+ overhead in our Command structure, around 100-200 bytes), so I'm just starting
+ with 2. Further analysis would be needed to determine the best value.
+ */
+ sendable = Math.min(sendable, max / 2);
} catch (InterruptedException e) {
- throw (IOException)new InterruptedIOException().initCause(e);
+ throw (IOException) new InterruptedIOException().initCause(e);
}
- channel.send(new Chunk(channel.newIoId(),oid,cbuf,off,sendable));
+ channel.send(new Chunk(channel.newIoId(), oid, cbuf, off, sendable));
window.decrease(sendable);
- off+=sendable;
- len-=sendable;
+ off += sendable;
+ len -= sendable;
}
}
}
@Override
public synchronized void flush() throws IOException {
- if(channel!=null && channel.remoteCapability.supportsProxyWriter2_35())
- channel.send(new Flush(channel.newIoId(),oid));
+ if (channel != null && channel.remoteCapability.supportsProxyWriter2_35()) {
+ channel.send(new Flush(channel.newIoId(), oid));
+ }
}
@Override
@@ -224,11 +229,13 @@ public void error(@CheckForNull Throwable cause) throws IOException {
}
synchronized (this) {
- //TODO: Bug. If the channel cannot send the command, the channel object will be never released and garbage collected
+ // TODO: Bug. If the channel cannot send the command, the channel object will be never released and garbage
+ // collected
if (channel != null) {
- // Close the writer on the remote side. This call may be invoked multiple times until the channel is released
- //TODO: send cause over the channel
- channel.send(new EOF(channel.newIoId(), oid/*,error*/));
+ // Close the writer on the remote side. This call may be invoked multiple times until the channel is
+ // released
+ // TODO: send cause over the channel
+ channel.send(new EOF(channel.newIoId(), oid /*,error*/));
channel = null;
channelReleased = true;
oid = -1;
@@ -237,17 +244,18 @@ public void error(@CheckForNull Throwable cause) throws IOException {
}
@Override
- //TODO: really?
+ // TODO: really?
@SuppressFBWarnings(value = "FI_FINALIZER_NULLS_FIELDS", justification = "As designed")
protected synchronized void finalize() throws Throwable {
super.finalize();
// if we haven't done so, release the exported object on the remote side.
// if the object is auto-unexported, the export entry could have already been removed.
- if(channel!=null) {
- if (channel.remoteCapability.supportsProxyWriter2_35())
- channel.send(new Unexport(channel.newIoId(),oid));
- else
- channel.send(new EOF(channel.newIoId(),oid));
+ if (channel != null) {
+ if (channel.remoteCapability.supportsProxyWriter2_35()) {
+ channel.send(new Unexport(channel.newIoId(), oid));
+ } else {
+ channel.send(new EOF(channel.newIoId(), oid));
+ }
channel = null;
oid = -1;
}
@@ -268,11 +276,11 @@ public Chunk(int ioId, int oid, char[] buf, int start, int len) {
super(false);
this.ioId = ioId;
this.oid = oid;
- if (start==0 && len==buf.length)
+ if (start == 0 && len == buf.length) {
this.buf = buf;
- else {
+ } else {
this.buf = new char[len];
- System.arraycopy(buf,start,this.buf,0,len);
+ System.arraycopy(buf, start, this.buf, 0, len);
}
}
@@ -284,8 +292,9 @@ protected void execute(final Channel channel) throws ExecutionException {
os.write(buf);
} catch (IOException e) {
try {
- if (channel.remoteCapability.supportsProxyWriter2_35())
+ if (channel.remoteCapability.supportsProxyWriter2_35()) {
channel.send(new NotifyDeadWriter(channel, e, oid));
+ }
} catch (ChannelClosedException x) {
// the other direction can be already closed if the connection
// shut down is initiated from this side. In that case, remain silent.
@@ -312,7 +321,7 @@ protected void execute(final Channel channel) throws ExecutionException {
@Override
public String toString() {
- return "ProxyWriter.Chunk("+oid+","+buf.length+")";
+ return "ProxyWriter.Chunk(" + oid + "," + buf.length + ")";
}
private static final long serialVersionUID = 1L;
@@ -346,7 +355,7 @@ protected void execute(Channel channel) throws ExecutionException {
@Override
public String toString() {
- return "ProxyWriter.Flush("+oid+")";
+ return "ProxyWriter.Flush(" + oid + ")";
}
private static final long serialVersionUID = 1L;
@@ -370,12 +379,12 @@ public Unexport(int ioId, int oid) {
@Override
protected void execute(final Channel channel) {
- channel.pipeWriter.submit(ioId, () -> channel.unexport(oid,createdAt,false));
+ channel.pipeWriter.submit(ioId, () -> channel.unexport(oid, createdAt, false));
}
@Override
public String toString() {
- return "ProxyWriter.Unexport("+oid+")";
+ return "ProxyWriter.Unexport(" + oid + ")";
}
private static final long serialVersionUID = 1L;
@@ -388,7 +397,7 @@ private static final class EOF extends Command {
private final int oid;
private final int ioId;
- public EOF(int ioId,int oid) {
+ public EOF(int ioId, int oid) {
this.ioId = ioId;
this.oid = oid;
}
@@ -402,7 +411,7 @@ protected void execute(final Channel channel) {
return;
}
channel.pipeWriter.submit(ioId, () -> {
- channel.unexport(oid,createdAt,false);
+ channel.unexport(oid, createdAt, false);
try {
os.close();
} catch (IOException e) {
@@ -413,7 +422,7 @@ protected void execute(final Channel channel) {
@Override
public String toString() {
- return "ProxyWriter.EOF("+oid+")";
+ return "ProxyWriter.EOF(" + oid + ")";
}
private static final long serialVersionUID = 1L;
@@ -447,7 +456,7 @@ protected void execute(Channel channel) {
@Override
public String toString() {
- return "ProxyWriter.Ack("+oid+','+size+")";
+ return "ProxyWriter.Ack(" + oid + ',' + size + ")";
}
private static final long serialVersionUID = 1L;
@@ -460,8 +469,8 @@ public String toString() {
private static final class NotifyDeadWriter extends Command {
private final int oid;
- private NotifyDeadWriter(Channel channel,Throwable cause, int oid) {
- super(channel,cause);
+ private NotifyDeadWriter(Channel channel, Throwable cause, int oid) {
+ super(channel, cause);
this.oid = oid;
}
@@ -473,7 +482,7 @@ protected void execute(Channel channel) {
@Override
public String toString() {
- return "ProxyWriter.Dead("+oid+")";
+ return "ProxyWriter.Dead(" + oid + ")";
}
private static final long serialVersionUID = 1L;
diff --git a/src/main/java/hudson/remoting/RemoteClassLoader.java b/src/main/java/hudson/remoting/RemoteClassLoader.java
index 5bbdfd6f0..34655c5b5 100644
--- a/src/main/java/hudson/remoting/RemoteClassLoader.java
+++ b/src/main/java/hudson/remoting/RemoteClassLoader.java
@@ -64,12 +64,9 @@
* @author Kohsuke Kawaguchi
*/
@SuppressFBWarnings(
- value = {
- "DMI_COLLECTION_OF_URLS",
- "DMI_BLOCKING_METHODS_ON_URL",
- "SIC_INNER_SHOULD_BE_STATIC_ANON"
- },
- justification = "Since this is based on the URLClassLoader, it is difficult to switch to URIs. We have no indication this causes noticeable resource issues. The implementations here and in URL reduce the impact.")
+ value = {"DMI_COLLECTION_OF_URLS", "DMI_BLOCKING_METHODS_ON_URL", "SIC_INNER_SHOULD_BE_STATIC_ANON"},
+ justification =
+ "Since this is based on the URLClassLoader, it is difficult to switch to URIs. We have no indication this causes noticeable resource issues. The implementations here and in URL reduce the impact.")
final class RemoteClassLoader extends URLClassLoader {
private static final Logger LOGGER = Logger.getLogger(RemoteClassLoader.class.getName());
@@ -100,7 +97,8 @@ interface Interruptible {
* This sleep keeps it from hammering the channel if there is a failure.
* The default value is 100 (ms).
*/
- static int RETRY_SLEEP_DURATION_MILLISECONDS = Integer.getInteger(RemoteClassLoader.class.getName() + "retrySleepDurationMilliseconds", 100);
+ static int RETRY_SLEEP_DURATION_MILLISECONDS =
+ Integer.getInteger(RemoteClassLoader.class.getName() + "retrySleepDurationMilliseconds", 100);
/**
* The total number of retries for an interrupted class load.
* This makes the operation retry for an extended period of time but eventually timeout.
@@ -167,13 +165,16 @@ public static ClassLoader create(@CheckForNull ClassLoader parent, @NonNull ICla
String name;
try {
name = proxy.getName();
- } catch(IOException ignored) {
+ } catch (IOException ignored) {
name = String.format(Locale.ROOT, "unknown-due-to-io-error %1$#x", System.identityHashCode(proxy));
} catch (IllegalStateException ignored) {
// IllegalStateException is thrown if the method does not exist on the remote side.
// TODO remove this at some point in the future when Jenkins sets the minimum remoting version to
// 3244.vf7f977e04755 or higher
- name = String.format(Locale.ROOT, "upgrade-remoting-to-3244.vf7f977e04755-or-higher %1$#x", System.identityHashCode(proxy));
+ name = String.format(
+ Locale.ROOT,
+ "upgrade-remoting-to-3244.vf7f977e04755-or-higher %1$#x",
+ System.identityHashCode(proxy));
}
return new RemoteClassLoader(name, parent, proxy);
}
@@ -248,17 +249,17 @@ private Class> fetchFromProxy(String name, Channel channel) throws ClassNotFou
}
private Class> loadWithMultiClassLoader(String name, Channel channel) throws ClassNotFoundException {
- /*
- In multi-classloader setup, RemoteClassLoaders do not retain the relationships among the original classloaders,
- so each RemoteClassLoader ends up loading classes on its own without delegating to other RemoteClassLoaders.
+ /*
+ In multi-classloader setup, RemoteClassLoaders do not retain the relationships among the original classloaders,
+ so each RemoteClassLoader ends up loading classes on its own without delegating to other RemoteClassLoaders.
- See the classloader X/Y examples in HUDSON-5048 for the depiction of the problem.
+ See the classloader X/Y examples in HUDSON-5048 for the depiction of the problem.
- So instead, we find the right RemoteClassLoader to load the class on per class basis.
- The communication is optimized for the single classloader use, by always returning the class file image
- along with the reference to the initiating ClassLoader (if the initiating ClassLoader has already loaded this class,
- then the class file image is wasted.)
- */
+ So instead, we find the right RemoteClassLoader to load the class on per class basis.
+ The communication is optimized for the single classloader use, by always returning the class file image
+ along with the reference to the initiating ClassLoader (if the initiating ClassLoader has already loaded this class,
+ then the class file image is wasted.)
+ */
long startTime = System.nanoTime();
ClassReference cr;
if (channel.remoteCapability.supportsPrefetch()) {
@@ -279,7 +280,8 @@ then the class file image is wasted.)
}
}
- private Class> loadRemoteClass(String name, Channel channel, ClassReference cr, RemoteClassLoader rcl) throws ClassNotFoundException {
+ private Class> loadRemoteClass(String name, Channel channel, ClassReference cr, RemoteClassLoader rcl)
+ throws ClassNotFoundException {
synchronized (rcl.getClassLoadingLock(name)) {
Class> c = rcl.findLoadedClass(name);
@@ -314,7 +316,8 @@ private Class> loadRemoteClass(String name, Channel channel, ClassReference cr
// but we need to remember to set the interrupt flag back on
// before we leave this call.
sleepForRetry();
- LOGGER.finer("Handling interrupt while loading remote class. Current retry count = " + tries + ", maximum = " + MAX_RETRIES);
+ LOGGER.finer("Handling interrupt while loading remote class. Current retry count = " + tries
+ + ", maximum = " + MAX_RETRIES);
continue;
}
break;
@@ -342,8 +345,8 @@ private boolean hasMoreRetries(int tries) {
private boolean isRetryException(Throwable e) {
return e instanceof InterruptedException
|| (e instanceof RemotingSystemException
- && (e.getCause() instanceof InterruptedException
- || e.getCause() instanceof InterruptedIOException));
+ && (e.getCause() instanceof InterruptedException
+ || e.getCause() instanceof InterruptedIOException));
}
private ClassReference prefetchClassReference(String name, Channel channel) throws ClassNotFoundException {
@@ -396,7 +399,7 @@ ClassReference toRef(ClassFile2 cf) {
ref.rememberIn(cn, this);
}
- LOGGER.log(Level.FINER, "prefetch {0} -> {1}", new Object[]{name, cn});
+ LOGGER.log(Level.FINER, "prefetch {0} -> {1}", new Object[] {name, cn});
}
ref.rememberIn(cn, ref.classLoader);
@@ -410,7 +413,8 @@ ClassReference toRef(ClassFile2 cf) {
// but we need to remember to set the interrupt flag back on
// before we leave this call.
sleepForRetry();
- LOGGER.finer("Handling interrupt while fetching class reference. Current retry count = " + tries + ", maximum = " + MAX_RETRIES);
+ LOGGER.finer("Handling interrupt while fetching class reference. Current retry count = " + tries
+ + ", maximum = " + MAX_RETRIES);
continue;
}
throw determineRemotingSystemException(x);
@@ -451,7 +455,8 @@ private Class> loadClassFile(String name, byte[] bytes) throws LinkageError {
short bytecodeLevel = (short) ((bytes[6] << 8) + (bytes[7] & 0xFF) - 44);
final Channel channel = channel();
if (channel != null && bytecodeLevel > channel.maximumBytecodeLevel) {
- throw new UnsupportedClassVersionError("this channel is restricted to JDK 1." + channel.maximumBytecodeLevel + " compatibility but " + name + " was compiled for 1." + bytecodeLevel);
+ throw new UnsupportedClassVersionError("this channel is restricted to JDK 1." + channel.maximumBytecodeLevel
+ + " compatibility but " + name + " was compiled for 1." + bytecodeLevel);
}
// if someone else is forcing us to load a class by giving as bytecode,
@@ -460,11 +465,12 @@ private Class> loadClassFile(String name, byte[] bytes) throws LinkageError {
definePackage(name);
- //TODO: probably this wrapping is not required anymore
+ // TODO: probably this wrapping is not required anymore
try {
return defineClass(name, bytes, 0, bytes.length);
} catch (UnsupportedClassVersionError e) {
- throw (UnsupportedClassVersionError) new UnsupportedClassVersionError("Failed to load " + name).initCause(e);
+ throw (UnsupportedClassVersionError)
+ new UnsupportedClassVersionError("Failed to load " + name).initCause(e);
} catch (ClassFormatError e) {
throw (ClassFormatError) new ClassFormatError("Failed to load " + name).initCause(e);
} catch (LinkageError e) {
@@ -484,7 +490,7 @@ private void definePackage(String name) {
}
String packageName = name.substring(0, idx);
- if (getPackage(packageName) != null) { // already defined
+ if (getPackage(packageName) != null) { // already defined
return;
}
@@ -507,7 +513,7 @@ public URL findResource(String name) {
if (resourceMap.containsKey(name)) {
URLish f = resourceMap.get(name);
if (f == null) {
- return null; // no such resource
+ return null; // no such resource
}
URL u = f.toURL();
if (u != null) {
@@ -544,7 +550,8 @@ public URL findResource(String name) {
// but we need to remember to set the interrupt flag back on
// before we leave this call.
sleepForRetry();
- LOGGER.finer("Handling interrupt while finding resource. Current retry count = " + tries + ", maximum = " + MAX_RETRIES);
+ LOGGER.finer("Handling interrupt while finding resource. Current retry count = " + tries
+ + ", maximum = " + MAX_RETRIES);
continue;
}
throw determineRemotingSystemException(x);
@@ -575,7 +582,7 @@ private static Vector toURLs(Vector src) throws MalformedURLExcepti
for (URLish s : src) {
URL u = s.toURL();
if (u == null) {
- return null; // abort
+ return null; // abort
}
r.add(u);
}
@@ -639,7 +646,8 @@ public Enumeration findResources(String name) throws IOException {
// but we need to remember to set the interrupt flag back on
// before we leave this call.
sleepForRetry();
- LOGGER.finer("Handling interrupt while finding resource. Current retry count = " + tries + ", maximum = " + MAX_RETRIES);
+ LOGGER.finer("Handling interrupt while finding resource. Current retry count = " + tries
+ + ", maximum = " + MAX_RETRIES);
continue;
}
throw determineRemotingSystemException(x);
@@ -667,7 +675,6 @@ public static void deleteDirectoryOnExit(File dir) {
Util.deleteDirectoryOnExit(dir);
}
-
/**
* Prefetches the jar into this class loader.
*
@@ -717,7 +724,6 @@ void rememberIn(String className, ClassLoader cl) {
rcl.prefetchedClasses.put(className, this);
}
}
-
}
/**
@@ -730,6 +736,7 @@ public static class ClassFile implements Serializable {
* oid of the classloader that should load this class.
*/
final int classLoader;
+
final byte[] classImage;
ClassFile(int classLoader, byte[] classImage) {
@@ -762,8 +769,10 @@ public static class ResourceFile implements Serializable {
* this points to the location of the resource. Used by
* the sender side to retrieve the resource when necessary.
*/
- @SuppressFBWarnings(value = "SE_TRANSIENT_FIELD_NOT_RESTORED", justification = "We're fine with the default null on the recipient side")
- transient final URL local;
+ @SuppressFBWarnings(
+ value = "SE_TRANSIENT_FIELD_NOT_RESTORED",
+ justification = "We're fine with the default null on the recipient side")
+ final transient URL local;
/**
* Fall back for creating a direct resource
@@ -816,8 +825,10 @@ public static class ClassFile2 extends ResourceFile {
* While this object is still on the sender side, used to remember the actual
* class that this {@link ClassFile2} represents.
*/
- @SuppressFBWarnings(value = "SE_TRANSIENT_FIELD_NOT_RESTORED", justification = "We're fine with the default null on the recipient side")
- transient final Class> clazz;
+ @SuppressFBWarnings(
+ value = "SE_TRANSIENT_FIELD_NOT_RESTORED",
+ justification = "We're fine with the default null on the recipient side")
+ final transient Class> clazz;
ClassFile2(int classLoader, ResourceImageRef image, ClassFile2 referer, Class> clazz, URL local) {
super(image, local);
@@ -930,7 +941,9 @@ public static void pin(ClassLoader cl, Channel local) {
// check if this is a remote classloader from the channel
final RemoteClassLoader rcl = (RemoteClassLoader) cl;
int oid = RemoteInvocationHandler.unwrap(rcl.proxy, local);
- if (oid != -1) return;
+ if (oid != -1) {
+ return;
+ }
}
local.pin(new ClassLoaderProxy(cl, local));
}
@@ -956,7 +969,9 @@ public ClassLoaderProxy(@NonNull ClassLoader cl, Channel channel) {
}
@Override
- @SuppressFBWarnings(value = "URLCONNECTION_SSRF_FD", justification = "This is only used for managing the jar cache as files.")
+ @SuppressFBWarnings(
+ value = "URLCONNECTION_SSRF_FD",
+ justification = "This is only used for managing the jar cache as files.")
public byte[] fetchJar(URL url) throws IOException {
return Util.readFully(url.openStream());
}
@@ -995,9 +1010,7 @@ public ClassFile fetch2(String className) throws ClassNotFoundException {
if (in == null) {
throw new ClassNotFoundException(className + " (" + ecl + " did not find class file)");
}
- return new ClassFile(
- exportId(ecl, channel),
- Util.readFully(in));
+ return new ClassFile(exportId(ecl, channel), Util.readFully(in));
} catch (IOException e) {
throw new ClassNotFoundException();
}
@@ -1019,7 +1032,8 @@ public ClassFile2 fetch4(String className, @CheckForNull ClassFile2 referer) thr
if (USE_BOOTSTRAP_CLASSLOADER) {
ecl = PSEUDO_BOOTSTRAP;
} else {
- throw new ClassNotFoundException("Bootstrap pseudo-classloader disabled: " + className + " via " + referrerClass);
+ throw new ClassNotFoundException(
+ "Bootstrap pseudo-classloader disabled: " + className + " via " + referrerClass);
}
}
@@ -1028,7 +1042,7 @@ public ClassFile2 fetch4(String className, @CheckForNull ClassFile2 referer) thr
try {
File jar = Which.jarFile(c);
- if (jar.isFile()) {// for historical reasons the jarFile method can return a directory
+ if (jar.isFile()) { // for historical reasons the jarFile method can return a directory
Checksum sum = channel.jarLoader.calcChecksum(jar);
ResourceImageRef imageRef;
@@ -1037,7 +1051,9 @@ public ClassFile2 fetch4(String className, @CheckForNull ClassFile2 referer) thr
// send the image as well, so as not to require another call to get this class loaded
imageRef = new ResourceImageBoth(urlOfClassFile, sum);
} else { // otherwise just send the checksum and save space
- imageRef = new ResourceImageInJar(sum, null /* TODO: we need to check if the URL of c points to the expected location of the file */);
+ imageRef = new ResourceImageInJar(
+ sum,
+ null /* TODO: we need to check if the URL of c points to the expected location of the file */);
}
return new ClassFile2(exportId(ecl, channel), imageRef, referer, c, urlOfClassFile);
@@ -1053,7 +1069,9 @@ public ClassFile2 fetch4(String className, @CheckForNull ClassFile2 referer) thr
}
@Override
- @SuppressFBWarnings(value = "URLCONNECTION_SSRF_FD", justification = "This is only used for managing the jar cache as files.")
+ @SuppressFBWarnings(
+ value = "URLCONNECTION_SSRF_FD",
+ justification = "This is only used for managing the jar cache as files.")
public Map fetch3(String className) throws ClassNotFoundException {
ClassFile2 cf = fetch4(className, null);
Map all = new HashMap<>();
@@ -1116,11 +1134,11 @@ public ResourceFile getResource2(String name) throws IOException {
private ResourceFile makeResource(String name, URL resource) throws IOException {
try {
File jar = Which.jarFile(resource, name);
- if (jar.isFile()) {// for historical reasons the jarFile method can return a directory
+ if (jar.isFile()) { // for historical reasons the jarFile method can return a directory
Checksum sum = channel.jarLoader.calcChecksum(jar);
ResourceImageRef ir;
if (!channel.jarLoader.isPresentOnRemote(sum)) {
- ir = new ResourceImageBoth(resource, sum); // remote probably doesn't have
+ ir = new ResourceImageBoth(resource, sum); // remote probably doesn't have
} else {
ir = new ResourceImageInJar(sum, null);
}
@@ -1133,7 +1151,8 @@ private ResourceFile makeResource(String name, URL resource) throws IOException
}
@Override
- @SuppressFBWarnings(value = "PZLA_PREFER_ZERO_LENGTH_ARRAYS",
+ @SuppressFBWarnings(
+ value = "PZLA_PREFER_ZERO_LENGTH_ARRAYS",
justification = "Null return value is a part of the public interface")
@CheckForNull
public byte[] getResource(String name) throws IOException {
@@ -1242,7 +1261,7 @@ public String toString() {
* resolve back to the instance on the server.
*/
private static class RemoteIClassLoader implements IClassLoader, SerializableOnlyOverRemoting {
- private transient final IClassLoader proxy;
+ private final transient IClassLoader proxy;
private final int oid;
private RemoteIClassLoader(int oid, IClassLoader proxy) {
@@ -1361,7 +1380,6 @@ public ResourceFile[] getResources2(String name) throws IOException {
public String getName() throws IOException {
throw new IOException("Cannot getName", cause);
}
-
}
private static Iterable analyze(InputStream bytecode) {
@@ -1379,7 +1397,8 @@ private static Iterable analyze(InputStream bytecode) {
* By default, classes that belong to the bootstrap classloader will NOT be remoted, as each JVM gets its own JRE
* and their versions can be potentially different.
*/
- public static boolean USE_BOOTSTRAP_CLASSLOADER = Boolean.getBoolean(RemoteClassLoader.class.getName() + ".useBootstrapClassLoader");
+ public static boolean USE_BOOTSTRAP_CLASSLOADER =
+ Boolean.getBoolean(RemoteClassLoader.class.getName() + ".useBootstrapClassLoader");
private static final Enumeration EMPTY_ENUMERATION = new Vector().elements();
}
diff --git a/src/main/java/hudson/remoting/RemoteInputStream.java b/src/main/java/hudson/remoting/RemoteInputStream.java
index 2c29fca49..1a981e65f 100644
--- a/src/main/java/hudson/remoting/RemoteInputStream.java
+++ b/src/main/java/hudson/remoting/RemoteInputStream.java
@@ -1,18 +1,18 @@
/*
* The MIT License
- *
+ *
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -78,21 +78,24 @@ public RemoteInputStream(InputStream core) {
*/
@Deprecated
public RemoteInputStream(InputStream core, boolean autoUnexport) {
- this(core, RemoteInputStream.Flag.NOT_GREEDY, autoUnexport ? RemoteInputStream.Flag.NOT_GREEDY : RemoteInputStream.Flag.MANUAL_UNEXPORT);
+ this(
+ core,
+ RemoteInputStream.Flag.NOT_GREEDY,
+ autoUnexport ? RemoteInputStream.Flag.NOT_GREEDY : RemoteInputStream.Flag.MANUAL_UNEXPORT);
}
/**
* @since 2.35
*/
public RemoteInputStream(InputStream core, Flag f) {
- this(core,EnumSet.of(f));
+ this(core, EnumSet.of(f));
}
/**
* @since 2.35
*/
public RemoteInputStream(InputStream core, Flag f1, Flag f2) {
- this(core,EnumSet.of(f1,f2));
+ this(core, EnumSet.of(f1, f2));
}
/**
@@ -101,8 +104,9 @@ public RemoteInputStream(InputStream core, Flag f1, Flag f2) {
public RemoteInputStream(InputStream core, Set flags) {
this.core = core;
greedy = flags.contains(RemoteInputStream.Flag.GREEDY);
- if (greedy)
+ if (greedy) {
greedyAt = new Greedy();
+ }
autoUnexport = !flags.contains(RemoteInputStream.Flag.MANUAL_UNEXPORT);
}
@@ -118,8 +122,8 @@ private void writeObject(ObjectOutputStream oos) throws IOException {
new Thread("RemoteInputStream greedy pump thread: " + greedyAt.print()) {
{
- setUncaughtExceptionHandler(
- (t, e) -> LOGGER.log(Level.SEVERE, "Uncaught exception in RemoteInputStream pump thread " + t, e));
+ setUncaughtExceptionHandler((t, e) -> LOGGER.log(
+ Level.SEVERE, "Uncaught exception in RemoteInputStream pump thread " + t, e));
setDaemon(true);
}
@@ -131,7 +135,9 @@ public void run() {
while (true) {
try {
len = i.read(buf);
- if (len < 0) break;
+ if (len < 0) {
+ break;
+ }
} catch (IOException e) {
// if we can propagate the error, do so. In any case, give up
if (o instanceof ErrorPropagatingOutputStream) {
@@ -175,13 +181,15 @@ public void run() {
oos.writeInt(id);
}
- @SuppressFBWarnings(value = "DESERIALIZATION_GADGET", justification = "Serializable only over remoting. Class filtering is done through JEP-200.")
+ @SuppressFBWarnings(
+ value = "DESERIALIZATION_GADGET",
+ justification = "Serializable only over remoting. Class filtering is done through JEP-200.")
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
final Channel channel = getChannelForSerialization();
if (channel.remoteCapability.supportsGreedyRemoteInputStream()) {
boolean greedy = ois.readBoolean();
if (greedy) {
- Pipe p = (Pipe)ois.readObject();
+ Pipe p = (Pipe) ois.readObject();
this.core = p.getIn();
return;
}
@@ -258,11 +266,11 @@ public String print() {
}
}
-//
-//
-// delegation to core
-//
-//
+ //
+ //
+ // delegation to core
+ //
+ //
@Override
public int read() throws IOException {
diff --git a/src/main/java/hudson/remoting/RemoteInvocationHandler.java b/src/main/java/hudson/remoting/RemoteInvocationHandler.java
index d37ae062a..802e41a6a 100644
--- a/src/main/java/hudson/remoting/RemoteInvocationHandler.java
+++ b/src/main/java/hudson/remoting/RemoteInvocationHandler.java
@@ -58,7 +58,7 @@
*
* @author Kohsuke Kawaguchi
*/
-//TODO: Likely should be serializable over Remoting logic, but this class has protection logic
+// TODO: Likely should be serializable over Remoting logic, but this class has protection logic
// Use-cases need to be investigated
@SuppressFBWarnings(value = "DESERIALIZATION_GADGET", justification = "This class has protection logic.")
final class RemoteInvocationHandler implements InvocationHandler, Serializable {
@@ -132,9 +132,14 @@ final class RemoteInvocationHandler implements InvocationHandler, Serializable {
/**
* Creates a proxy that wraps an existing OID on the remote.
*/
- private RemoteInvocationHandler(Channel channel, int id, boolean userProxy,
- boolean autoUnexportByCaller, boolean userSpace,
- Class> proxyType, boolean recordCreatedAt) {
+ private RemoteInvocationHandler(
+ Channel channel,
+ int id,
+ boolean userProxy,
+ boolean autoUnexportByCaller,
+ boolean userSpace,
+ Class> proxyType,
+ boolean recordCreatedAt) {
this.channel = channel == null ? null : channel.ref();
this.oid = id;
this.userProxy = userProxy;
@@ -152,18 +157,27 @@ private RemoteInvocationHandler(Channel channel, int id, boolean userProxy,
* @param recordCreatedAt as in {@link Command#Command(boolean)}
*/
@NonNull
- static T wrap(Channel channel, int id, Class