package org.archive.util.binsearch.impl; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URISyntaxException; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.HeadMethod; import org.archive.util.binsearch.SeekableLineReader; public class HTTPSeakableLineReader implements SeekableLineReader { private final static String CONTENT_LENGTH = "Content-Length"; private int blockSize = 128 * 1024; private HttpClient http; private String url; private long length; private BufferedReader br; private InputStreamReader isr; private HttpMethod activeMethod; public HTTPSeakableLineReader(HttpClient http, String url) throws HttpException, URISyntaxException, IOException { this.http = http; this.url = url; acquireLength(); } private void acquireLength() throws URISyntaxException, HttpException, IOException { HttpMethod head = new HeadMethod(url); int code = http.executeMethod(head); if(code != 200) { throw new IOException("Unable to retrieve from " + url); } Header lengthHeader = head.getResponseHeader(CONTENT_LENGTH); if(lengthHeader == null) { throw new IOException("No Content-Length header for " + url); } String val = lengthHeader.getValue(); try { length = Long.parseLong(val); } catch(NumberFormatException e) { throw new IOException("Bad Content-Length value " +url+ ": " + val); } } public void seek(long offset) throws IOException { if(activeMethod != null) { activeMethod.abort(); activeMethod.releaseConnection(); } activeMethod = new GetMethod(url); activeMethod.setRequestHeader("Range", String.format("bytes=%d-", offset)); int code = http.executeMethod(activeMethod); if((code != 206) && (code != 200)) { throw new IOException("Non 200/6 response code for " + url + ":" + offset); } isr = new InputStreamReader(activeMethod.getResponseBodyAsStream(), UTF8); br = new BufferedReader(isr, blockSize); } public String readLine() throws IOException { if(br == null) { seek(0); } return br.readLine(); } public void close() throws IOException { if(activeMethod != null) { activeMethod.abort(); activeMethod.releaseConnection(); } if(br != null) { br = null; } if(isr != null) { isr = null; } } public long getSize() throws IOException { return length; } }