pax_global_header 0000666 0000000 0000000 00000000064 11576524460 0014524 g ustar 00root root 0000000 0000000 52 comment=03a5f080d19e701b3a27f1ee34488decf4c5a538
kohsuke-robust-http-client-c2b0488/ 0000775 0000000 0000000 00000000000 11576524460 0017276 5 ustar 00root root 0000000 0000000 kohsuke-robust-http-client-c2b0488/pom.xml 0000664 0000000 0000000 00000006346 11576524460 0020624 0 ustar 00root root 0000000 0000000 4.0.0org.jvnet.robust-http-clientrobust-http-client1.2Robust HTTP client libraryInputStream that hides automatic download retryhttp://${project.artifactId}.kohsuke.org/scm:git:git@github.com/kohsuke/${project.artifactId}.gitscm:git:ssh://git@github.com/kohsuke/${project.artifactId}.githttp://${project.artifactId}.kohsuke.org/maven.jenkins-ci.orghttp://maven.jenkins-ci.org:8081/content/repositories/releasesmaven.jenkins-ci.orghttp://maven.jenkins-ci.org:8081/content/repositories/snapshotsgithub-pagesgitsite:git@github.com/kohsuke/${project.artifactId}.gitmaven-compiler-plugin1.51.5org.apache.maven.pluginsmaven-idea-pluginJDK1.5trueorg.apache.maven.pluginsmaven-site-plugin3.0-beta-3org.apache.maven.scmmaven-scm-provider-gitexe1.3org.apache.maven.scmmaven-scm-manager-plexus1.3org.kathrynhuxtable.maven.wagonwagon-gitsite0.3.1junitjunit3.8.1testcommons-iocommons-io1.4testMIT licensehttp://www.opensource.org/licenses/mit-license.phprepom.g.o-publichttp://maven.glassfish.org/content/groups/public/
kohsuke-robust-http-client-c2b0488/src/ 0000775 0000000 0000000 00000000000 11576524460 0020065 5 ustar 00root root 0000000 0000000 kohsuke-robust-http-client-c2b0488/src/main/ 0000775 0000000 0000000 00000000000 11576524460 0021011 5 ustar 00root root 0000000 0000000 kohsuke-robust-http-client-c2b0488/src/main/java/ 0000775 0000000 0000000 00000000000 11576524460 0021732 5 ustar 00root root 0000000 0000000 kohsuke-robust-http-client-c2b0488/src/main/java/org/ 0000775 0000000 0000000 00000000000 11576524460 0022521 5 ustar 00root root 0000000 0000000 kohsuke-robust-http-client-c2b0488/src/main/java/org/jvnet/ 0000775 0000000 0000000 00000000000 11576524460 0023647 5 ustar 00root root 0000000 0000000 kohsuke-robust-http-client-c2b0488/src/main/java/org/jvnet/robust_http_client/ 0000775 0000000 0000000 00000000000 11576524460 0027562 5 ustar 00root root 0000000 0000000 RetryableHttpStream.java 0000664 0000000 0000000 00000013035 11576524460 0034315 0 ustar 00root root 0000000 0000000 kohsuke-robust-http-client-c2b0488/src/main/java/org/jvnet/robust_http_client /*
* The MIT License
*
* Copyright (c) 2009, Sun Microsystems, Inc.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.jvnet.robust_http_client;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URL;
/**
* {@link InputStream} implementation around {@link HttpURLConnection} that automatically reconnects
* if the connection fails in the middle.
*
* @author Kohsuke Kawaguchi
*/
public class RetryableHttpStream extends InputStream {
/**
* Where are we downloading from?
*/
public final URL url;
/**
* Proxy, or null none is explicitly given (Java runtime may still decide to use a proxy, though.)
*/
protected final Proxy proxy;
/**
* Total bytes of the entity.
*/
public final int totalLength;
/**
* Number of bytes read so far.
*/
protected int read;
/**
* Current underlying InputStream.
*/
private InputStream in;
/**
* {@link HttpURLConnection} to allow the caller to access HTTP resposne headers.
* Do not use {@link HttpURLConnection#getInputStream()}, however.
*/
public final HttpURLConnection connection;
/**
* Connects to the given HTTP/HTTPS URL, by using the proxy auto-configured by the Java runtime.
*/
public RetryableHttpStream(URL url) throws IOException {
this(url,null);
}
/**
* Connects to the given HTTP/HTTPS URL, by using the specified proxy.
*
* @param proxy
* To force a direct connection, pass in {@link Proxy#NO_PROXY}.
*/
public RetryableHttpStream(URL url, Proxy proxy) throws IOException {
this.url = url;
if (!url.getProtocol().startsWith("http"))
throw new IllegalArgumentException(url+" is not an HTTP URL");
this.proxy = proxy;
connection = connect();
totalLength = connection.getContentLength();
in = getStream(connection);
}
/**
* Hook for tests.
*/
/*package*/ InputStream getStream(HttpURLConnection con) throws IOException {
return con.getInputStream();
}
/**
* Opens the URL and makes a connection.
*/
protected HttpURLConnection connect() throws IOException {
return (HttpURLConnection)(proxy != null ? url.openConnection(proxy) : url.openConnection());
}
/**
* Reconnect and fast-forward until a desired position.
*/
private void reconnect() throws IOException {
while(true) {
shallWeRetry();
HttpURLConnection con = connect();
con.setRequestProperty("Range","bytes="+read+"-");
con.connect();
String cr = con.getHeaderField("Content-Range");
in = getStream(con);
if (cr!=null && cr.startsWith("bytes "+read+"-")) {
// server responded with a range
return;
} else {
// server sent us the whole thing again. fast-forward till where we want
int bytesToSkip=read;
while(true) {
long l = in.skip(bytesToSkip);
if (l==0)
break; // hit EOF. do it all over again
bytesToSkip-=l;
if (bytesToSkip==0)
return; // fast forward complete
}
}
}
}
/**
* Subclass can override this method to determine if we should continue to retry, or abort.
*
*
* If this method returns normally, we'll retry. By default, this method retries 5 times then quits.
*
* @throws IOException
* to abort the processing.
*/
protected void shallWeRetry() throws IOException {
if (nRetry++>5)
throw new IOException("Too many failures. Aborting.");
}
private int nRetry;
@Override
public int read() throws IOException {
while(true) {
int ch = in.read();
if (ch>=0) {
read++;
return ch;
}
if(read>=totalLength)
return -1; // EOF expected
reconnect();
}
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
while(true) {
int r = in.read(b, off, len);
if (r>=0) {
read+=r;
return r;
}
if(read>=totalLength)
return -1; // EOF expected
reconnect();
}
}
}
kohsuke-robust-http-client-c2b0488/src/site/ 0000775 0000000 0000000 00000000000 11576524460 0021031 5 ustar 00root root 0000000 0000000 kohsuke-robust-http-client-c2b0488/src/site/site.xml 0000664 0000000 0000000 00000001140 11576524460 0022513 0 ustar 00root root 0000000 0000000
org.kohsukemaven-skin1.1
${reports}
kohsuke-robust-http-client-c2b0488/src/test/ 0000775 0000000 0000000 00000000000 11576524460 0021044 5 ustar 00root root 0000000 0000000 kohsuke-robust-http-client-c2b0488/src/test/java/ 0000775 0000000 0000000 00000000000 11576524460 0021765 5 ustar 00root root 0000000 0000000 kohsuke-robust-http-client-c2b0488/src/test/java/org/ 0000775 0000000 0000000 00000000000 11576524460 0022554 5 ustar 00root root 0000000 0000000 kohsuke-robust-http-client-c2b0488/src/test/java/org/jvnet/ 0000775 0000000 0000000 00000000000 11576524460 0023702 5 ustar 00root root 0000000 0000000 kohsuke-robust-http-client-c2b0488/src/test/java/org/jvnet/robust_http_client/ 0000775 0000000 0000000 00000000000 11576524460 0027615 5 ustar 00root root 0000000 0000000 kohsuke-robust-http-client-c2b0488/src/test/java/org/jvnet/robust_http_client/AppTest.java 0000664 0000000 0000000 00000004351 11576524460 0032043 0 ustar 00root root 0000000 0000000 package org.jvnet.robust_http_client;
import junit.framework.TestCase;
import java.net.URL;
import java.net.HttpURLConnection;
import java.io.IOException;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import static java.lang.Math.max;
import java.security.MessageDigest;
import java.security.DigestInputStream;
import java.util.Arrays;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.CountingOutputStream;
import org.apache.commons.io.output.NullOutputStream;
public class AppTest extends TestCase
{
public void test1() throws Exception {
URL url = new URL("http://archive.apache.org/dist/ant/binaries/apache-ant-1.6.5-bin.zip");
RetryableHttpStream s = new RetryableHttpStream(url) {
int retry=0;
@Override
protected void shallWeRetry() throws IOException {
System.out.println("Retrying");
if(retry++>16)
throw new IOException("Too many retries");
}
/**
* Simulate the EOF in the middle.
*/
@Override
InputStream getStream(HttpURLConnection con) throws IOException {
byte[] b = new byte[1024*1024];
int len=0;
while(len