Improve stream handling
Close streams on error paths, ensure flush, and use consistent buffer size. Also add and use stream utilities.
This commit is contained in:
parent
d02dd290ca
commit
2e665e2771
@ -21,10 +21,10 @@
|
|||||||
package org.fdroid.fdroid;
|
package org.fdroid.fdroid;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
public class Downloader extends Thread {
|
public class Downloader extends Thread {
|
||||||
@ -94,6 +94,8 @@ public class Downloader extends Thread {
|
|||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
|
InputStream input = null;
|
||||||
|
OutputStream output = null;
|
||||||
String apkname = curapk.apkName;
|
String apkname = curapk.apkName;
|
||||||
localfile = new File(DB.getDataPath(), apkname);
|
localfile = new File(DB.getDataPath(), apkname);
|
||||||
try {
|
try {
|
||||||
@ -127,30 +129,23 @@ public class Downloader extends Thread {
|
|||||||
status = Status.RUNNING;
|
status = Status.RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferedInputStream getit = new BufferedInputStream(new URL(
|
input = new URL(remotefile).openStream();
|
||||||
remotefile).openStream(), 8192);
|
output = new FileOutputStream(localfile);
|
||||||
|
byte data[] = new byte[Utils.BUFFER_SIZE];
|
||||||
FileOutputStream saveit = new FileOutputStream(localfile);
|
while (true) {
|
||||||
BufferedOutputStream bout = new BufferedOutputStream(saveit, 1024);
|
|
||||||
byte data[] = new byte[1024];
|
|
||||||
|
|
||||||
int totalRead = 0;
|
|
||||||
int bytesRead = getit.read(data, 0, 1024);
|
|
||||||
while (bytesRead != -1) {
|
|
||||||
if (isInterrupted()) {
|
if (isInterrupted()) {
|
||||||
Log.d("FDroid", "Download cancelled!");
|
Log.d("FDroid", "Download cancelled!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bout.write(data, 0, bytesRead);
|
int count = input.read(data);
|
||||||
totalRead += bytesRead;
|
if (count == -1) {
|
||||||
synchronized (this) {
|
break;
|
||||||
progress = totalRead;
|
}
|
||||||
|
output.write(data, 0, count);
|
||||||
|
synchronized (this) {
|
||||||
|
progress += count;
|
||||||
}
|
}
|
||||||
bytesRead = getit.read(data, 0, 1024);
|
|
||||||
}
|
}
|
||||||
bout.close();
|
|
||||||
getit.close();
|
|
||||||
saveit.close();
|
|
||||||
|
|
||||||
if (isInterrupted()) {
|
if (isInterrupted()) {
|
||||||
localfile.delete();
|
localfile.delete();
|
||||||
@ -182,6 +177,9 @@ public class Downloader extends Thread {
|
|||||||
status = Status.ERROR;
|
status = Status.ERROR;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
Utils.closeQuietly(output);
|
||||||
|
Utils.closeQuietly(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d("FDroid", "Download finished: " + localfile);
|
Log.d("FDroid", "Download finished: " + localfile);
|
||||||
|
@ -62,15 +62,16 @@ public class Hasher {
|
|||||||
else if (file != null) {
|
else if (file != null) {
|
||||||
byte[] buffer = new byte[1024];
|
byte[] buffer = new byte[1024];
|
||||||
int read = 0;
|
int read = 0;
|
||||||
|
InputStream input = null;
|
||||||
try {
|
try {
|
||||||
InputStream is = new BufferedInputStream(
|
input = new BufferedInputStream(new FileInputStream(file));
|
||||||
new FileInputStream(file));
|
while ((read = input.read(buffer)) > 0) {
|
||||||
while ((read = is.read(buffer)) > 0) {
|
|
||||||
digest.update(buffer, 0, read);
|
digest.update(buffer, 0, read);
|
||||||
}
|
}
|
||||||
is.close();
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return hashCache = "";
|
return hashCache = "";
|
||||||
|
} finally {
|
||||||
|
Utils.closeQuietly(input);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
digest.update(array);
|
digest.update(array);
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
package org.fdroid.fdroid;
|
package org.fdroid.fdroid;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@ -265,23 +263,16 @@ public class RepoXMLHandler extends DefaultHandler {
|
|||||||
int totalBytes = 0;
|
int totalBytes = 0;
|
||||||
int code = uc.getResponseCode();
|
int code = uc.getResponseCode();
|
||||||
if (code == 200) {
|
if (code == 200) {
|
||||||
|
InputStream input = null;
|
||||||
FileOutputStream f = ctx.openFileOutput(dest, Context.MODE_PRIVATE);
|
OutputStream output = null;
|
||||||
|
try {
|
||||||
BufferedInputStream getit = new BufferedInputStream(
|
input = new URL(url).openStream();
|
||||||
new URL(url).openStream());
|
output = ctx.openFileOutput(dest, Context.MODE_PRIVATE);
|
||||||
BufferedOutputStream bout = new BufferedOutputStream(f, 1024);
|
Utils.copy(input, output);
|
||||||
byte data[] = new byte[1024];
|
} finally {
|
||||||
|
Utils.closeQuietly(output);
|
||||||
int readed = getit.read(data, 0, 1024);
|
Utils.closeQuietly(input);
|
||||||
while (readed != -1) {
|
|
||||||
totalBytes += readed;
|
|
||||||
bout.write(data, 0, readed);
|
|
||||||
readed = getit.read(data, 0, 1024);
|
|
||||||
}
|
}
|
||||||
bout.close();
|
|
||||||
getit.close();
|
|
||||||
f.close();
|
|
||||||
|
|
||||||
String et = uc.getHeaderField("ETag");
|
String et = uc.getHeaderField("ETag");
|
||||||
if (et != null)
|
if (et != null)
|
||||||
@ -322,33 +313,33 @@ public class RepoXMLHandler extends DefaultHandler {
|
|||||||
repo.lastetag, newetag);
|
repo.lastetag, newetag);
|
||||||
if (code == 200) {
|
if (code == 200) {
|
||||||
String jarpath = ctx.getFilesDir() + "/tempindex.jar";
|
String jarpath = ctx.getFilesDir() + "/tempindex.jar";
|
||||||
JarFile jar;
|
JarFile jar = null;
|
||||||
JarEntry je;
|
JarEntry je;
|
||||||
|
Certificate[] certs;
|
||||||
try {
|
try {
|
||||||
jar = new JarFile(jarpath, true);
|
jar = new JarFile(jarpath, true);
|
||||||
je = (JarEntry) jar.getEntry("index.xml");
|
je = (JarEntry) jar.getEntry("index.xml");
|
||||||
File efile = new File(ctx.getFilesDir(),
|
File efile = new File(ctx.getFilesDir(),
|
||||||
"/tempindex.xml");
|
"/tempindex.xml");
|
||||||
InputStream in = new BufferedInputStream(
|
InputStream input = null;
|
||||||
jar.getInputStream(je), 8192);
|
OutputStream output = null;
|
||||||
OutputStream out = new BufferedOutputStream(
|
try {
|
||||||
new FileOutputStream(efile), 8192);
|
input = jar.getInputStream(je);
|
||||||
byte[] buffer = new byte[8192];
|
output = new FileOutputStream(efile);
|
||||||
while (true) {
|
Utils.copy(input, output);
|
||||||
int nBytes = in.read(buffer);
|
} finally {
|
||||||
if (nBytes <= 0)
|
Utils.closeQuietly(output);
|
||||||
break;
|
Utils.closeQuietly(input);
|
||||||
out.write(buffer, 0, nBytes);
|
|
||||||
}
|
}
|
||||||
out.flush();
|
certs = je.getCertificates();
|
||||||
out.close();
|
|
||||||
in.close();
|
|
||||||
} catch (SecurityException e) {
|
} catch (SecurityException e) {
|
||||||
Log.e("FDroid", "Invalid hash for index file");
|
Log.e("FDroid", "Invalid hash for index file");
|
||||||
return "Invalid hash for index file";
|
return "Invalid hash for index file";
|
||||||
|
} finally {
|
||||||
|
if (jar != null) {
|
||||||
|
jar.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Certificate[] certs = je.getCertificates();
|
|
||||||
jar.close();
|
|
||||||
if (certs == null) {
|
if (certs == null) {
|
||||||
Log.d("FDroid", "No signature found in index");
|
Log.d("FDroid", "No signature found in index");
|
||||||
return "No signature found in index";
|
return "No signature found in index";
|
||||||
|
@ -18,10 +18,10 @@
|
|||||||
|
|
||||||
package org.fdroid.fdroid;
|
package org.fdroid.fdroid;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
@ -290,21 +290,16 @@ public class UpdateService extends IntentService {
|
|||||||
URL u = new URL(server + "/icons/" + app.icon);
|
URL u = new URL(server + "/icons/" + app.icon);
|
||||||
HttpURLConnection uc = (HttpURLConnection) u.openConnection();
|
HttpURLConnection uc = (HttpURLConnection) u.openConnection();
|
||||||
if (uc.getResponseCode() == 200) {
|
if (uc.getResponseCode() == 200) {
|
||||||
BufferedInputStream getit = new BufferedInputStream(
|
InputStream input = null;
|
||||||
uc.getInputStream());
|
OutputStream output = null;
|
||||||
FileOutputStream saveit = new FileOutputStream(f);
|
try {
|
||||||
BufferedOutputStream bout = new BufferedOutputStream(saveit,
|
input = uc.getInputStream();
|
||||||
1024);
|
output = new FileOutputStream(f);
|
||||||
byte data[] = new byte[1024];
|
Utils.copy(input, output);
|
||||||
|
} finally {
|
||||||
int readed = getit.read(data, 0, 1024);
|
Utils.closeQuietly(output);
|
||||||
while (readed != -1) {
|
Utils.closeQuietly(input);
|
||||||
bout.write(data, 0, readed);
|
|
||||||
readed = getit.read(data, 0, 1024);
|
|
||||||
}
|
}
|
||||||
bout.close();
|
|
||||||
getit.close();
|
|
||||||
saveit.close();
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
55
src/org/fdroid/fdroid/Utils.java
Normal file
55
src/org/fdroid/fdroid/Utils.java
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010-12 Ciaran Gultnieks, ciaran@ciarang.com
|
||||||
|
*
|
||||||
|
* This program is 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; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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 org.fdroid.fdroid;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public final class Utils {
|
||||||
|
private Utils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final int BUFFER_SIZE = 4096;
|
||||||
|
|
||||||
|
public static void copy(InputStream input, OutputStream output)
|
||||||
|
throws IOException {
|
||||||
|
byte[] buffer = new byte[BUFFER_SIZE];
|
||||||
|
while (true) {
|
||||||
|
int count = input.read(buffer);
|
||||||
|
if (count == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
output.write(buffer, 0, count);
|
||||||
|
}
|
||||||
|
output.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void closeQuietly(Closeable closeable) {
|
||||||
|
if (closeable == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
closeable.close();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user