in core/src/main/java/hudson/FilePath.java [854:940]
private boolean installIfNecessaryFrom(@NonNull URL archive, @NonNull TaskListener listener, @NonNull String message, int maxRedirects) throws InterruptedException, IOException {
try {
FilePath timestamp = this.child(".timestamp");
long lastModified = timestamp.lastModified();
URLConnection con;
try {
con = ProxyConfiguration.open(archive);
if (lastModified != 0) {
con.setIfModifiedSince(lastModified);
}
con.connect();
} catch (IOException x) {
if (this.exists()) {
// Cannot connect now, so assume whatever was last unpacked is still OK.
listener.getLogger().println("Skipping installation of " + archive + " to " + remote + ": " + x);
return false;
} else {
throw x;
}
}
if (con instanceof HttpURLConnection) {
HttpURLConnection httpCon = (HttpURLConnection) con;
int responseCode = httpCon.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_MOVED_PERM
|| responseCode == HttpURLConnection.HTTP_MOVED_TEMP) {
// follows redirect
if (maxRedirects > 0) {
String location = httpCon.getHeaderField("Location");
listener.getLogger().println("Following redirect " + archive.toExternalForm() + " -> " + location);
return installIfNecessaryFrom(getUrlFactory().newURL(location), listener, message, maxRedirects - 1);
} else {
listener.getLogger().println("Skipping installation of " + archive + " to " + remote + " due to too many redirects.");
return false;
}
}
if (lastModified != 0) {
if (responseCode == HttpURLConnection.HTTP_NOT_MODIFIED) {
return false;
} else if (responseCode != HttpURLConnection.HTTP_OK) {
listener.getLogger().println("Skipping installation of " + archive + " to " + remote + " due to server error: " + responseCode + " " + httpCon.getResponseMessage());
return false;
}
}
}
long sourceTimestamp = con.getLastModified();
if(this.exists()) {
if (lastModified != 0 && sourceTimestamp == lastModified)
return false; // already up to date
this.deleteContents();
} else {
this.mkdirs();
}
listener.getLogger().println(message);
if (isRemote()) {
// First try to download from the agent machine.
try {
act(new Unpack(archive));
timestamp.touch(sourceTimestamp);
return true;
} catch (IOException x) {
Functions.printStackTrace(x, listener.error("Failed to download " + archive + " from agent; will retry from master"));
}
}
// for HTTP downloads, enable automatic retry for added resilience
InputStream in = archive.getProtocol().startsWith("http") ? ProxyConfiguration.getInputStream(archive) : con.getInputStream();
CountingInputStream cis = new CountingInputStream(in);
try {
if(archive.toExternalForm().endsWith(".zip"))
unzipFrom(cis);
else
untarFrom(cis,GZIP);
} catch (IOException e) {
throw new IOException(String.format("Failed to unpack %s (%d bytes read of total %d)",
archive,cis.getByteCount(),con.getContentLength()),e);
}
timestamp.touch(sourceTimestamp);
return true;
} catch (IOException e) {
throw new IOException("Failed to install "+archive+" to "+remote,e);
}
}