diff --git a/src/main/java/hudson/remoting/Engine.java b/src/main/java/hudson/remoting/Engine.java index 96a2b11a2..15484e12d 100644 --- a/src/main/java/hudson/remoting/Engine.java +++ b/src/main/java/hudson/remoting/Engine.java @@ -128,6 +128,7 @@ public void run() { * This value is determined from {@link #candidateUrls} after a successful connection. * Note that this URL DOES NOT have "tcpSlaveAgentListener" in it. */ + @CheckForNull private URL hudsonUrl; private final String secretKey; @@ -171,6 +172,12 @@ public void setJarCache(JarCache jarCache) { this.jarCache = jarCache; } + /** + * Provides Jenkins URL if available. + * @return Jenkins URL. May return {@code null} if the connection is not established or if the URL cannot be determined + * in the {@link JnlpAgentEndpointResolver}. + */ + @CheckForNull public URL getHudsonUrl() { return hudsonUrl; } @@ -334,6 +341,7 @@ private void innerRun(IOHub hub, SSLContext context, ExecutorService service) { events.status("Could not resolve server among " + candidateUrls); return; } + hudsonUrl = endpoint.getServiceUrl(); events.status(String.format("Agent discovery successful%n" + " Agent address: %s%n" diff --git a/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpoint.java b/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpoint.java index 203b45d9e..af58d7afc 100644 --- a/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpoint.java +++ b/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpoint.java @@ -29,6 +29,7 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; +import java.net.URL; import java.nio.channels.SocketChannel; import java.security.interfaces.RSAPublicKey; import java.util.Collections; @@ -65,7 +66,23 @@ public class JnlpAgentEndpoint { */ @CheckForNull private final Set protocols; + + /** + * Jenkins URL for the discovered endpoint. + * @since TODO + */ + @CheckForNull + private final URL serviceUrl; + /** + * @deprecated Use {@link #JnlpAgentEndpoint(java.lang.String, int, java.security.interfaces.RSAPublicKey, java.util.Set, java.lang.String)} + */ + @Deprecated + public JnlpAgentEndpoint(@Nonnull String host, int port, @CheckForNull RSAPublicKey publicKey, + @CheckForNull Set protocols) { + this(host, port, publicKey, protocols, null); + } + /** * Constructor for a remote {@code Jenkins} instance. * @@ -73,9 +90,12 @@ public class JnlpAgentEndpoint { * @param port the port. * @param publicKey the {@code InstanceIdentity.getPublic()} of the remote instance (if known). * @param protocols The supported protocols. + * @param serviceURL URL of the service hosting the remoting endpoint. + * Use {@code null} if it is not a web service or if the URL cannot be determined + * @since TODO */ public JnlpAgentEndpoint(@Nonnull String host, int port, @CheckForNull RSAPublicKey publicKey, - @CheckForNull Set protocols) { + @CheckForNull Set protocols, @CheckForNull URL serviceURL) { if (port <= 0 || 65536 <= port) { throw new IllegalArgumentException("Port " + port + " is not in the range 1-65535"); } @@ -83,6 +103,7 @@ public JnlpAgentEndpoint(@Nonnull String host, int port, @CheckForNull RSAPublic this.port = port; this.publicKey = publicKey; this.protocols = protocols == null ? null : Collections.unmodifiableSet(new LinkedHashSet(protocols)); + this.serviceUrl = serviceURL; } /** @@ -95,6 +116,15 @@ public InetSocketAddress getAddress() { return new InetSocketAddress(host, port); } + /** + * Retrieves URL of the web service providing the remoting endpoint. + * @return Service URL if available. {@code null} otherwise. + */ + @CheckForNull + public URL getServiceUrl() { + return serviceUrl; + } + /** * Gets the hostname. * diff --git a/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpointResolver.java b/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpointResolver.java index 5ba2bda58..2984d80d5 100644 --- a/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpointResolver.java +++ b/src/main/java/org/jenkinsci/remoting/engine/JnlpAgentEndpointResolver.java @@ -127,7 +127,16 @@ public void setTunnel(String tunnel) { public JnlpAgentEndpoint resolve() throws IOException { IOException firstError = null; for (String jenkinsUrl : jenkinsUrls) { - URL salURL = toAgentListenerURL(jenkinsUrl); + + final URL selectedJenkinsURL; + final URL salURL; + try { + selectedJenkinsURL = new URL(jenkinsUrl); + salURL = toAgentListenerURL(jenkinsUrl); + } catch (MalformedURLException ex) { + LOGGER.log(Level.WARNING, String.format("Cannot parse agent endpoint URL %s. Skipping it", jenkinsUrl), ex); + continue; + } // find out the TCP port HttpURLConnection con = @@ -223,7 +232,8 @@ public int compare(String o1, String o2) { if (tokens[0].length() > 0) host = tokens[0]; if (tokens[1].length() > 0) port = Integer.parseInt(tokens[1]); } - return new JnlpAgentEndpoint(host, port, identity, agentProtocolNames); + + return new JnlpAgentEndpoint(host, port, identity, agentProtocolNames, selectedJenkinsURL); } finally { con.disconnect(); }