/*
* Universal Media Server, for streaming any media to DLNA
* compatible renderers based on the http://www.ps3mediaserver.org.
* Copyright (C) 2012 UMS developers.
*
* This program is a free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License only.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package net.pms.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;
/**
* Downloads URLs
*
* @author Tim Cox (mail@tcox.org)
*/
public class UriRetriever {
private static final String HTTP_HEADER_CONTENT_LENGTH = "Content-Length";
private static final int BUFFER_SIZE = 1024;
private HttpClient client = new HttpClient();
public byte[] get(String uri) throws IOException {
HttpMethod method = new GetMethod(uri);
try {
int statusCode = client.executeMethod(method);
if (statusCode != HttpStatus.SC_OK) {
throw new IOException("HTTP response not OK");
}
return method.getResponseBody();
} catch (HttpException e) {
throw new IOException("Unable to download by HTTP" + e.getMessage());
} finally {
method.releaseConnection();
}
}
public byte[] getWithCallback(String uri, UriRetrieverCallback callback) throws IOException {
HttpMethod getMethod = null;
try {
getMethod = startGetRequest(uri, callback);
int totalBytes = getContentSize(uri, getMethod);
byte[] data = pullData(uri, getMethod, callback, totalBytes);
return data;
} catch (HttpException e) {
throw new IOException("Unable to download via HTTP: " + uri + ": " + e.getMessage());
} catch (IOException e) {
throw new IOException("Unable to download via HTTP: " + uri + ": " + e.getMessage());
} finally {
if (getMethod != null) {
getMethod.releaseConnection();
}
}
}
private HttpMethod startGetRequest(String uri, UriRetrieverCallback callback) throws HttpException, IOException {
int statusCode = -1;
HttpMethod method = new GetMethod(uri);
configureMethod(method);
statusCode = client.executeMethod(method);
if (statusCode != HttpStatus.SC_OK) {
throw new IOException("HTTP result code was not OK");
}
return method;
}
private void configureMethod(HttpMethod method) {
method.setRequestHeader("User-Agent", "UMS");
method.setFollowRedirects(true);
}
private static byte[] pullData(String uri, HttpMethod method, UriRetrieverCallback callback, int totalBytes) throws IOException {
int bytesWritten = 0;
InputStream input = method.getResponseBodyAsStream();
ByteArrayOutputStream output = new ByteArrayOutputStream(totalBytes);
byte[] buffer = new byte[BUFFER_SIZE];
int count = -1;
while ((count = input.read(buffer)) != -1) {
output.write(buffer, 0, count);
bytesWritten += count;
invokeCallback(uri, callback, totalBytes, bytesWritten);
}
output.flush();
output.close();
return output.toByteArray();
}
private static void invokeCallback(String uri, UriRetrieverCallback callback, int totalBytes, int bytesWritten) throws IOException {
try {
callback.progressMade(uri, bytesWritten, totalBytes);
} catch (UriRetrieverCallback.CancelDownloadException e) {
throw new IOException("Download was cancelled");
}
}
private int getContentSize(String uri, HttpMethod method) {
Header header = method.getResponseHeader(HTTP_HEADER_CONTENT_LENGTH);
if (header != null) {
String value = "" + header.getValue();
int totalBytes = -1;
try {
totalBytes = Integer.parseInt(value);
} catch (NumberFormatException e) {
return 0;
}
return totalBytes;
} else {
return 0;
}
}
}