Bug 875401 - Switch HealthReportGenerator to use org.json.JSONObject/JSONArray. r=nalexander

This commit is contained in:
Richard Newman 2013-05-28 12:01:34 -07:00
parent 138d8529b0
commit 960fe22b3c
2 changed files with 116 additions and 43 deletions

View File

@ -4,10 +4,8 @@
package org.mozilla.gecko.background.healthreport;
import java.util.HashMap;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.background.common.log.Logger;
import org.mozilla.gecko.background.healthreport.HealthReportStorage.Field;
@ -32,8 +30,9 @@ public class HealthReportGenerator {
/**
* @return null if no environment could be computed, or else the resulting document.
* @throws JSONException if there was an error adding environment data to the resulting document.
*/
public JSONObject generateDocument(long since, long lastPingTime, String profilePath) {
public JSONObject generateDocument(long since, long lastPingTime, String profilePath) throws JSONException {
Logger.info(LOG_TAG, "Generating FHR document from " + since + "; last ping " + lastPingTime + ", for profile " + profilePath);
ProfileInformationCache cache = new ProfileInformationCache(profilePath);
if (!cache.restoreUnlessInitialized()) {
@ -55,8 +54,9 @@ public class HealthReportGenerator {
*</ul>
*
* <code>days</code> is a map from date strings to <tt>{hash: {measurement: {_v: version, fields...}}}</tt>.
* @throws JSONException if there was an error adding environment data to the resulting document.
*/
public JSONObject generateDocument(long since, long lastPingTime, Environment currentEnvironment) {
public JSONObject generateDocument(long since, long lastPingTime, Environment currentEnvironment) throws JSONException {
Logger.debug(LOG_TAG, "Current environment hash: " + currentEnvironment.getHash());
// We want to map field IDs to some strings as we go.
@ -64,26 +64,21 @@ public class HealthReportGenerator {
JSONObject document = new JSONObject();
// Defeat "unchecked" warnings with JDK7. See Bug 875088.
@SuppressWarnings("unchecked")
HashMap<String, Object> doc = ((HashMap<String, Object>) document);
if (lastPingTime >= HealthReportConstants.EARLIEST_LAST_PING) {
doc.put("lastPingDate", HealthReportUtils.getDateString(lastPingTime));
document.put("lastPingDate", HealthReportUtils.getDateString(lastPingTime));
}
doc.put("thisPingDate", HealthReportUtils.getDateString(now()));
doc.put("version", PAYLOAD_VERSION);
document.put("thisPingDate", HealthReportUtils.getDateString(now()));
document.put("version", PAYLOAD_VERSION);
doc.put("environments", getEnvironmentsJSON(currentEnvironment, envs));
doc.put("data", getDataJSON(currentEnvironment, envs, since));
document.put("environments", getEnvironmentsJSON(currentEnvironment, envs));
document.put("data", getDataJSON(currentEnvironment, envs, since));
return document;
}
@SuppressWarnings("unchecked")
protected JSONObject getDataJSON(Environment currentEnvironment,
SparseArray<Environment> envs, long since) {
SparseArray<Environment> envs, long since) throws JSONException {
SparseArray<Field> fields = storage.getFieldsByID();
JSONObject days = getDaysJSON(currentEnvironment, envs, fields, since);
@ -96,8 +91,7 @@ public class HealthReportGenerator {
return data;
}
@SuppressWarnings("unchecked")
protected JSONObject getDaysJSON(Environment currentEnvironment, SparseArray<Environment> envs, SparseArray<Field> fields, long since) {
protected JSONObject getDaysJSON(Environment currentEnvironment, SparseArray<Environment> envs, SparseArray<Field> fields, long since) throws JSONException {
JSONObject days = new JSONObject();
Cursor cursor = storage.getRawEventsSince(since);
try {
@ -140,7 +134,7 @@ public class HealthReportGenerator {
}
final Field field = fields.get(cField);
JSONObject measurement = (JSONObject) envObject.get(field.measurementName);
JSONObject measurement = envObject.optJSONObject(field.measurementName);
if (measurement == null) {
// We will never have more than one measurement version within a
// single environment -- to do so involves changing the build ID. And
@ -151,15 +145,10 @@ public class HealthReportGenerator {
envObject.put(field.measurementName, measurement);
}
if (field.isDiscreteField()) {
JSONArray discrete = (JSONArray) measurement.get(field.fieldName);
if (discrete == null) {
discrete = new JSONArray();
measurement.put(field.fieldName, discrete);
}
if (field.isStringField()) {
discrete.add(cursor.getString(3));
HealthReportUtils.append(measurement, field.fieldName, cursor.getString(3));
} else if (field.isIntegerField()) {
discrete.add(cursor.getLong(3));
HealthReportUtils.append(measurement, field.fieldName, cursor.getLong(3));
} else {
// Uh oh!
throw new IllegalStateException("Unknown field type: " + field.flags);
@ -182,9 +171,8 @@ public class HealthReportGenerator {
return days;
}
@SuppressWarnings("unchecked")
protected JSONObject getEnvironmentsJSON(Environment currentEnvironment,
SparseArray<Environment> envs) {
SparseArray<Environment> envs) throws JSONException {
JSONObject environments = new JSONObject();
// Always do this, even if it hasn't recorded anything in the DB.
@ -201,8 +189,7 @@ public class HealthReportGenerator {
return environments;
}
@SuppressWarnings("unchecked")
private JSONObject jsonify(Environment e, Environment current) {
private JSONObject jsonify(Environment e, Environment current) throws JSONException {
JSONObject age = getProfileAge(e, current);
JSONObject sysinfo = getSysInfo(e, current);
JSONObject gecko = getGeckoInfo(e, current);
@ -231,8 +218,7 @@ public class HealthReportGenerator {
return out;
}
@SuppressWarnings("unchecked")
private JSONObject getProfileAge(Environment e, Environment current) {
private JSONObject getProfileAge(Environment e, Environment current) throws JSONException {
JSONObject age = new JSONObject();
int changes = 0;
if (current == null || current.profileCreation != e.profileCreation) {
@ -246,8 +232,7 @@ public class HealthReportGenerator {
return age;
}
@SuppressWarnings("unchecked")
private JSONObject getSysInfo(Environment e, Environment current) {
private JSONObject getSysInfo(Environment e, Environment current) throws JSONException {
JSONObject sysinfo = new JSONObject();
int changes = 0;
if (current == null || current.cpuCount != e.cpuCount) {
@ -277,8 +262,7 @@ public class HealthReportGenerator {
return sysinfo;
}
@SuppressWarnings("unchecked")
private JSONObject getGeckoInfo(Environment e, Environment current) {
private JSONObject getGeckoInfo(Environment e, Environment current) throws JSONException {
JSONObject gecko = new JSONObject();
int changes = 0;
if (current == null || !current.vendor.equals(e.vendor)) {
@ -328,8 +312,7 @@ public class HealthReportGenerator {
return gecko;
}
@SuppressWarnings("unchecked")
private JSONObject getAppInfo(Environment e, Environment current) {
private JSONObject getAppInfo(Environment e, Environment current) throws JSONException {
JSONObject appinfo = new JSONObject();
int changes = 0;
if (current == null || current.isBlocklistEnabled != e.isBlocklistEnabled) {
@ -347,8 +330,7 @@ public class HealthReportGenerator {
return appinfo;
}
@SuppressWarnings("unchecked")
private JSONObject getAddonCounts(Environment e, Environment current) {
private JSONObject getAddonCounts(Environment e, Environment current) throws JSONException {
JSONObject counts = new JSONObject();
int changes = 0;
if (current == null || current.extensionCount != e.extensionCount) {
@ -370,8 +352,7 @@ public class HealthReportGenerator {
return counts;
}
@SuppressWarnings("unchecked")
private JSONObject getActiveAddons(Environment e, Environment current) {
private JSONObject getActiveAddons(Environment e, Environment current) throws JSONException {
JSONObject active = new JSONObject();
int changes = 0;
if (current != null && changes == 0) {

View File

@ -5,9 +5,17 @@
package org.mozilla.gecko.background.healthreport;
import java.text.SimpleDateFormat;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import java.util.SortedSet;
import java.util.TimeZone;
import java.util.TreeSet;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONArray;
import org.mozilla.apache.commons.codec.digest.DigestUtils;
import android.content.ContentUris;
@ -45,4 +53,88 @@ public class HealthReportUtils {
public static Uri getEventURI(Uri environmentURI) {
return environmentURI.buildUpon().path("/events/" + ContentUris.parseId(environmentURI) + "/").build();
}
/**
* Copy the keys from the provided {@link JSONObject} into the provided {@link Set}.
*/
private static <T extends Set<String>> T intoKeySet(T keys, JSONObject o) {
if (o == null || o == JSONObject.NULL) {
return keys;
}
@SuppressWarnings("unchecked")
Iterator<String> it = o.keys();
while (it.hasNext()) {
keys.add(it.next());
}
return keys;
}
/**
* Produce a {@link SortedSet} containing the string keys of the provided
* object.
*
* @param o a {@link JSONObject} with string keys.
* @return a sorted set.
*/
public static SortedSet<String> sortedKeySet(JSONObject o) {
return intoKeySet(new TreeSet<String>(), o);
}
/**
* Produce a {@link Set} containing the string keys of the provided object.
* @param o a {@link JSONObject} with string keys.
* @return an unsorted set.
*/
public static Set<String> keySet(JSONObject o) {
return intoKeySet(new HashSet<String>(), o);
}
/**
* {@link JSONObject} doesn't provide a <code>clone</code> method, nor any
* useful constructors, so we do this the hard way.
*
* @return a new object containing the same keys and values as the old.
* @throws JSONException
* if JSONObject is even more stupid than expected and cannot store
* a value from the provided object in the new object. This should
* never happen.
*/
public static JSONObject shallowCopyObject(JSONObject o) throws JSONException {
if (o == null) {
return null;
}
JSONObject out = new JSONObject();
@SuppressWarnings("unchecked")
Iterator<String> keys = out.keys();
while (keys.hasNext()) {
final String key = keys.next();
out.put(key, o.get(key));
}
return out;
}
/**
* Just like {@link JSONObject#accumulate(String, Object)}, but doesn't do the wrong thing for single values.
* @throws JSONException
*/
public static void append(JSONObject o, String key, Object value) throws JSONException {
if (!o.has(key)) {
JSONArray arr = new JSONArray();
arr.put(value);
o.put(key, arr);
return;
}
Object dest = o.get(key);
if (dest instanceof JSONArray) {
((JSONArray) dest).put(value);
return;
}
JSONArray arr = new JSONArray();
arr.put(dest);
arr.put(value);
o.put(key, arr);
return;
}
}