package com.danikula.videocache;
import android.text.TextUtils;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import static com.danikula.videocache.Preconditions.checkNotNull;
import static java.net.HttpURLConnection.HTTP_OK;
import static java.net.HttpURLConnection.HTTP_PARTIAL;
/**
* {@link Source} that uses http resource as source for {@link ProxyCache}.
*
* @author Alexey Danilov (danikula@gmail.com).
*/
public class HttpUrlSource implements Source {
final String url;
private HttpURLConnection connection;
private InputStream inputStream;
private volatile int available = Integer.MIN_VALUE;
private volatile String mime;
public HttpUrlSource(String url) {
this(url, ProxyCacheUtils.getSupposablyMime(url));
}
public HttpUrlSource(String url, String mime) {
this.url = Preconditions.checkNotNull(url);
this.mime = mime;
}
@Override
public int available() throws ProxyCacheException {
if (available == Integer.MIN_VALUE) {
fetchContentInfo();
}
return available;
}
@Override
public void open(int offset) throws ProxyCacheException {
try {
Log.d(ProxyCacheUtils.LOG_TAG, "Open connection " + (offset > 0 ? " with offset " + offset : "") + " to " + url);
connection = (HttpURLConnection) new URL(url).openConnection();
if (offset > 0) {
connection.setRequestProperty("Range", "bytes=" + offset + "-");
}
mime = connection.getContentType();
inputStream = connection.getInputStream();
readSourceAvailableBytes(connection, offset);
} catch (IOException e) {
throw new ProxyCacheException("Error opening connection for " + url + " with offset " + offset, e);
}
}
private void readSourceAvailableBytes(HttpURLConnection connection, int offset) throws IOException {
int contentLength = connection.getContentLength();
int responseCode = connection.getResponseCode();
available = responseCode == HTTP_OK ? contentLength :
responseCode == HTTP_PARTIAL ? contentLength + offset :
available;
}
@Override
public void close() throws ProxyCacheException {
if (connection != null) {
connection.disconnect();
}
}
@Override
public int read(byte[] buffer) throws ProxyCacheException {
if (inputStream == null) {
throw new ProxyCacheException("Error reading data from " + url + ": connection is absent!");
}
try {
return inputStream.read(buffer, 0, buffer.length);
} catch (IOException e) {
throw new ProxyCacheException("Error reading data from " + url, e);
}
}
private void fetchContentInfo() throws ProxyCacheException {
Log.d(ProxyCacheUtils.LOG_TAG, "Read content info from " + url);
HttpURLConnection urlConnection = null;
try {
urlConnection = (HttpURLConnection) new URL(url).openConnection();
urlConnection.setRequestMethod("HEAD");
available = urlConnection.getContentLength();
mime = urlConnection.getContentType();
Log.d(ProxyCacheUtils.LOG_TAG, "Content-Length of " + url + " is " + available + " bytes, mime is " + mime);
} catch (IOException e) {
throw new ProxyCacheException("Error fetching Content-Length from " + url);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
}
public String getMime() throws ProxyCacheException {
if (TextUtils.isEmpty(mime)) {
fetchContentInfo();
}
return mime;
}
}