pax_global_header00006660000000000000000000000064115765244600014524gustar00rootroot0000000000000052 comment=03a5f080d19e701b3a27f1ee34488decf4c5a538 kohsuke-robust-http-client-c2b0488/000077500000000000000000000000001157652446000172765ustar00rootroot00000000000000kohsuke-robust-http-client-c2b0488/pom.xml000066400000000000000000000063461157652446000206240ustar00rootroot00000000000000 4.0.0 org.jvnet.robust-http-client robust-http-client 1.2 Robust HTTP client library InputStream that hides automatic download retry http://${project.artifactId}.kohsuke.org/ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ maven.jenkins-ci.org http://maven.jenkins-ci.org:8081/content/repositories/releases maven.jenkins-ci.org http://maven.jenkins-ci.org:8081/content/repositories/snapshots github-pages gitsite:git@github.com/kohsuke/${project.artifactId}.git maven-compiler-plugin 1.5 1.5 org.apache.maven.plugins maven-idea-plugin JDK1.5 true org.apache.maven.plugins maven-site-plugin 3.0-beta-3 org.apache.maven.scm maven-scm-provider-gitexe 1.3 org.apache.maven.scm maven-scm-manager-plexus 1.3 org.kathrynhuxtable.maven.wagon wagon-gitsite 0.3.1 junit junit 3.8.1 test commons-io commons-io 1.4 test MIT license http://www.opensource.org/licenses/mit-license.php repo m.g.o-public http://maven.glassfish.org/content/groups/public/ kohsuke-robust-http-client-c2b0488/src/000077500000000000000000000000001157652446000200655ustar00rootroot00000000000000kohsuke-robust-http-client-c2b0488/src/main/000077500000000000000000000000001157652446000210115ustar00rootroot00000000000000kohsuke-robust-http-client-c2b0488/src/main/java/000077500000000000000000000000001157652446000217325ustar00rootroot00000000000000kohsuke-robust-http-client-c2b0488/src/main/java/org/000077500000000000000000000000001157652446000225215ustar00rootroot00000000000000kohsuke-robust-http-client-c2b0488/src/main/java/org/jvnet/000077500000000000000000000000001157652446000236475ustar00rootroot00000000000000kohsuke-robust-http-client-c2b0488/src/main/java/org/jvnet/robust_http_client/000077500000000000000000000000001157652446000275625ustar00rootroot00000000000000RetryableHttpStream.java000066400000000000000000000130351157652446000343150ustar00rootroot00000000000000kohsuke-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/000077500000000000000000000000001157652446000210315ustar00rootroot00000000000000kohsuke-robust-http-client-c2b0488/src/site/site.xml000066400000000000000000000011401157652446000225130ustar00rootroot00000000000000 org.kohsuke maven-skin 1.1

${reports} kohsuke-robust-http-client-c2b0488/src/test/000077500000000000000000000000001157652446000210445ustar00rootroot00000000000000kohsuke-robust-http-client-c2b0488/src/test/java/000077500000000000000000000000001157652446000217655ustar00rootroot00000000000000kohsuke-robust-http-client-c2b0488/src/test/java/org/000077500000000000000000000000001157652446000225545ustar00rootroot00000000000000kohsuke-robust-http-client-c2b0488/src/test/java/org/jvnet/000077500000000000000000000000001157652446000237025ustar00rootroot00000000000000kohsuke-robust-http-client-c2b0488/src/test/java/org/jvnet/robust_http_client/000077500000000000000000000000001157652446000276155ustar00rootroot00000000000000kohsuke-robust-http-client-c2b0488/src/test/java/org/jvnet/robust_http_client/AppTest.java000066400000000000000000000043511157652446000320430ustar00rootroot00000000000000package 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