Bug 1356693 - infer: fix RESOURCE_LEAK's in services
The primary issue is that we use a throwing InputStreamReader
constructor. If it throws, then any nested streams will be lost.
We can fix that by using the non-throwing InputStreamReader
constructor (which uses a Charset as the second parameter,
instead of a String which causes an Exception to be thrown
if it can't be parsed)
We also simplify some nested Stream's a little: most of the
Stream constructors don't throw, so there's no harm in not keeping
individual references to those that don't throw - and that
results in less Stream references for us to handle.
MozReview-Commit-ID: 2hyRFGVmGnU
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/Utils.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/Utils.java
@@ -26,16 +26,17 @@ import java.util.TreeMap;
import java.util.concurrent.Executor;
import org.json.simple.JSONArray;
import org.mozilla.apache.commons.codec.binary.Base32;
import org.mozilla.apache.commons.codec.binary.Base64;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.background.nativecode.NativeCrypto;
import org.mozilla.gecko.sync.setup.Constants;
+import org.mozilla.gecko.util.IOUtils;
import org.mozilla.gecko.util.StringUtils;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
public class Utils {
@@ -483,47 +484,30 @@ public class Utils {
* @param filename name of file to read; must not be null.
* @return <code>String</code> instance.
*/
public static String readFile(final Context context, final String filename) {
if (filename == null) {
throw new IllegalArgumentException("Passed null filename in readFile.");
}
- FileInputStream fis = null;
- InputStreamReader isr = null;
BufferedReader br = null;
try {
- fis = context.openFileInput(filename);
- isr = new InputStreamReader(fis, StringUtils.UTF_8);
- br = new BufferedReader(isr);
+ br = new BufferedReader(new InputStreamReader(context.openFileInput(filename), StringUtils.UTF_8));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
return sb.toString();
} catch (Exception e) {
return null;
} finally {
- if (isr != null) {
- try {
- isr.close();
- } catch (IOException e) {
- // Ignore.
- }
- }
- if (fis != null) {
- try {
- fis.close();
- } catch (IOException e) {
- // Ignore.
- }
- }
+ IOUtils.safeStreamClose(br);
}
}
/**
* Format a duration as a string, like "0.56 seconds".
*
* @param startMillis start time in milliseconds.
* @param endMillis end time in milliseconds.
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/MozResponse.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/MozResponse.java
@@ -13,16 +13,17 @@ import java.util.Scanner;
import org.json.simple.JSONArray;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.sync.ExtendedJSONObject;
import org.mozilla.gecko.sync.NonArrayJSONException;
import org.mozilla.gecko.sync.NonObjectJSONException;
+import org.mozilla.gecko.util.IOUtils;
import org.mozilla.gecko.util.StringUtils;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpEntity;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.HttpStatus;
import ch.boye.httpclientandroidlib.impl.cookie.DateParseException;
import ch.boye.httpclientandroidlib.impl.cookie.DateUtils;
@@ -101,22 +102,22 @@ public class MozResponse {
return new ExtendedJSONObject(body);
}
HttpEntity entity = this.response.getEntity();
if (entity == null) {
throw new IOException("no entity");
}
- InputStream content = entity.getContent();
+ Reader in = null;
try {
- Reader in = new BufferedReader(new InputStreamReader(content, "UTF-8"));
+ in = new BufferedReader(new InputStreamReader(entity.getContent(), StringUtils.UTF_8));
return new ExtendedJSONObject(in);
} finally {
- content.close();
+ IOUtils.safeStreamClose(in);
}
}
public JSONArray jsonArrayBody() throws NonArrayJSONException, IOException {
final JSONParser parser = new JSONParser();
try {
if (body != null) {
// Do it from the cached String.