From bf01a16c759d175fb209cc7f8da31be14714a329 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Thu, 16 Jun 2022 11:04:51 -0300 Subject: [PATCH] [app] Remove jackson dependency Parsing of JSON is now done inside the index library using kotlinx.serialization multi-platform library. Another small usage in FDroidMetricsWorker was replaced with native JSONObject. --- app/build.gradle | 7 --- .../main/java/org/fdroid/fdroid/data/Apk.java | 27 +-------- .../main/java/org/fdroid/fdroid/data/App.java | 26 +-------- .../fdroid/work/FDroidMetricsWorker.java | 57 +++++++++++-------- 4 files changed, 36 insertions(+), 81 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index e895536ac..4a2aa7b52 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,9 +12,6 @@ def getVersionName = { -> return stdout.toString().trim() } -def isCi = "true" == System.getenv("CI") -def preDexEnabled = "true" == System.getProperty("pre-dex", "true") - def fullApplicationId = "org.fdroid.fdroid" def basicApplicationId = "org.fdroid.basic" // yes, this actually needs both quotes https://stackoverflow.com/a/41391841 @@ -170,10 +167,6 @@ dependencies { implementation 'io.reactivex.rxjava3:rxandroid:3.0.0' implementation 'io.reactivex.rxjava3:rxjava:3.0.9' - implementation 'com.fasterxml.jackson.core:jackson-core:2.11.4' - implementation 'com.fasterxml.jackson.core:jackson-annotations:2.11.4' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.4' - implementation "com.github.bumptech.glide:glide:4.12.0" annotationProcessor "com.github.bumptech.glide:compiler:4.12.0" diff --git a/app/src/main/java/org/fdroid/fdroid/data/Apk.java b/app/src/main/java/org/fdroid/fdroid/data/Apk.java index 00d51b746..06e5ff98e 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/Apk.java +++ b/app/src/main/java/org/fdroid/fdroid/data/Apk.java @@ -12,10 +12,6 @@ import android.os.Parcelable; import android.text.TextUtils; import android.webkit.MimeTypeMap; -import com.fasterxml.jackson.annotation.JacksonInject; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; - import org.fdroid.database.AppManifest; import org.fdroid.database.AppVersion; import org.fdroid.database.Repository; @@ -59,24 +55,16 @@ import androidx.annotation.VisibleForTesting; public class Apk implements Comparable, Parcelable { // Using only byte-range keeps it only 8-bits in the SQLite database - @JsonIgnore public static final int SDK_VERSION_MAX_VALUE = Byte.MAX_VALUE; - @JsonIgnore public static final int SDK_VERSION_MIN_VALUE = 0; public static final String RELEASE_CHANNEL_BETA = "Beta"; public static final String RELEASE_CHANNEL_STABLE = "Stable"; // these are never set by the Apk/package index metadata - @JsonIgnore public String repoAddress; - @JsonIgnore long repoVersion; - @JsonIgnore public SanitizedFile installedFile; // the .apk file on this device's filesystem - @JsonIgnore public boolean compatible; // True if compatible with the device. - - @JacksonInject("repoId") public long repoId; // the database ID of the repo it comes from // these come directly from the index metadata @@ -172,7 +160,7 @@ public class Apk implements Comparable, Parcelable { hashType = "sha256"; added = new Date(v.getAdded()); features = v.getFeatureNames().toArray(new String[0]); - packageName = v.getPackageName(); + setPackageName(v.getPackageName()); compatible = v.isCompatible(); AppManifest manifest = v.getManifest(); minSdkVersion = manifest.getUsesSdk() == null ? @@ -239,7 +227,6 @@ public class Apk implements Comparable, Parcelable { * * @see org.fdroid.fdroid.installer.InstallManagerService */ - @JsonIgnore // prevent tests from failing due to nulls in checkRepoAddress() public String getCanonicalUrl() { checkRepoAddress(); String address = repoAddress; @@ -417,8 +404,6 @@ public class Apk implements Comparable, Parcelable { /** * Set the Package Name property while ensuring it is sanitized. */ - @JsonProperty("packageName") - @SuppressWarnings("unused") void setPackageName(String packageName) { if (Utils.isSafePackageName(packageName)) { this.packageName = packageName; @@ -428,16 +413,6 @@ public class Apk implements Comparable, Parcelable { } } - @JsonProperty("uses-permission") - @SuppressWarnings("unused") - private void setUsesPermission(Object[][] permissions) { - } - - @JsonProperty("uses-permission-sdk-23") - @SuppressWarnings("unused") - private void setUsesPermissionSdk23(Object[][] permissions) { - } - /** * Generate the set of requested permissions for the current Android version. *

diff --git a/app/src/main/java/org/fdroid/fdroid/data/App.java b/app/src/main/java/org/fdroid/fdroid/data/App.java index 801357c8e..2c501a009 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/App.java +++ b/app/src/main/java/org/fdroid/fdroid/data/App.java @@ -17,9 +17,6 @@ import android.util.Log; import com.bumptech.glide.Glide; import com.bumptech.glide.RequestBuilder; -import com.fasterxml.jackson.annotation.JacksonInject; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; import org.fdroid.database.AppListItem; import org.fdroid.database.Repository; @@ -66,7 +63,6 @@ import androidx.core.os.LocaleListCompat; */ public class App implements Comparable, Parcelable { - @JsonIgnore private static final String TAG = "App"; /** @@ -74,7 +70,6 @@ public class App implements Comparable, Parcelable { * It is set globally static to a) cache this value, since there are thousands * of {@link App} entries, and b) make it easy to test} */ - @JsonIgnore public static LocaleListCompat systemLocaleList; public static LocaleListCompat getLocales() { @@ -90,29 +85,19 @@ public class App implements Comparable, Parcelable { /** * True if compatible with the device (i.e. if at least one apk is) */ - @JsonIgnore public boolean compatible; - @JsonIgnore public Apk installedApk; // might be null if not installed - @JsonIgnore public String installedSig; - @JsonIgnore public int installedVersionCode; - @JsonIgnore public String installedVersionName; - @JsonIgnore private long id; - @JsonIgnore public org.fdroid.database.AppPrefs prefs; - @JsonIgnore public String preferredSigner; - @JsonIgnore public boolean isApk; /** * Has this {@code App} been localized into one of the user's current locales. */ - @JsonIgnore boolean isLocalized; /** @@ -122,7 +107,6 @@ public class App implements Comparable, Parcelable { * the highest priority. The UI doesn't care normally _which_ repo provided the metadata. * This is required for getting the full URL to the various graphics and screenshots. */ - @JacksonInject("repoId") public long repoId; // the remaining properties are set directly from the index metadata @@ -130,7 +114,6 @@ public class App implements Comparable, Parcelable { public String name = "Unknown"; public String summary = "Unknown application"; - @JsonProperty("icon") public String iconFromApk; public String description; @@ -250,7 +233,7 @@ public class App implements Comparable, Parcelable { public App(final UpdatableApp app) { id = 0; repoId = app.getUpdate().getRepoId(); - packageName = app.getPackageName(); + setPackageName(app.getPackageName()); name = app.getName() == null ? "" : app.getName(); summary = app.getSummary() == null ? "" : app.getSummary(); installedVersionCode = (int) app.getInstalledVersionCode(); @@ -264,7 +247,7 @@ public class App implements Comparable, Parcelable { id = 0; repoId = app.getRepoId(); compatible = app.getMetadata().isCompatible(); - packageName = app.getPackageName(); + setPackageName(app.getPackageName()); name = app.getName() == null ? "" : app.getName(); summary = app.getSummary() == null ? "" : app.getSummary(); String desc = app.getDescription(getLocales()); @@ -329,7 +312,7 @@ public class App implements Comparable, Parcelable { public App(AppListItem item) { repoId = item.getRepoId(); - packageName = item.getPackageName(); + setPackageName(item.getPackageName()); name = item.getName() == null ? "" : item.getName(); summary = item.getSummary() == null ? "" : item.getSummary(); FileV2 iconFile = item.getIcon(getLocales()); @@ -381,7 +364,6 @@ public class App implements Comparable, Parcelable { * out to the database and used elsewhere, this is needed to intercept * the setting of {@link App#description} to insert the format method. */ - @JsonProperty("description") private void setDescription(String description) { // NOPMD this.description = formatDescription(description); } @@ -389,7 +371,6 @@ public class App implements Comparable, Parcelable { /** * Set the Package Name property while ensuring it is sanitized. */ - @JsonProperty("packageName") void setPackageName(String packageName) { if (Utils.isSafePackageName(packageName)) { this.packageName = packageName; @@ -919,7 +900,6 @@ public class App implements Comparable, Parcelable { this.id = in.readLong(); } - @JsonIgnore public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override public App createFromParcel(Parcel source) { diff --git a/app/src/main/java/org/fdroid/fdroid/work/FDroidMetricsWorker.java b/app/src/main/java/org/fdroid/fdroid/work/FDroidMetricsWorker.java index 617af4665..ddeeefbb5 100644 --- a/app/src/main/java/org/fdroid/fdroid/work/FDroidMetricsWorker.java +++ b/app/src/main/java/org/fdroid/fdroid/work/FDroidMetricsWorker.java @@ -24,13 +24,7 @@ import android.content.pm.PackageManager; import android.os.Build; import android.text.TextUtils; import android.text.format.DateUtils; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.MapperFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; +import android.util.Log; import org.apache.commons.io.FileUtils; import org.fdroid.download.HttpPoster; @@ -38,6 +32,9 @@ import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.installer.InstallHistoryService; import org.fdroid.fdroid.net.DownloaderFactory; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; import java.io.File; import java.io.IOException; @@ -281,13 +278,10 @@ public class FDroidMetricsWorker extends Worker { EVENTS.addAll(parseInstallHistoryCsv(context, weekStart)); cleanInsightsReport.events = EVENTS.toArray(new MatomoEvent[0]); - ObjectMapper mapper = new ObjectMapper(); - mapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY); - mapper.enable(SerializationFeature.INDENT_OUTPUT); try { - return mapper.writeValueAsString(cleanInsightsReport); - } catch (JsonProcessingException e) { - e.printStackTrace(); + return cleanInsightsReport.getJsonString(); + } catch (JSONException e) { + Log.e(TAG, "Error getting json string", e); } return null; } @@ -300,14 +294,23 @@ public class FDroidMetricsWorker extends Worker { * @see Matomo Event Tracking */ private static class CleanInsightsReport { - @JsonProperty MatomoEvent[] events = new MatomoEvent[0]; - @JsonProperty final long idsite = 3; // NOPMD - @JsonProperty final String lang = Locale.getDefault().getLanguage(); - @JsonProperty final String ua = Utils.getUserAgent(); + + private String getJsonString() throws JSONException { + JSONObject json = new JSONObject(); + JSONArray array = new JSONArray(); + for (MatomoEvent event : events) { + array.put(event.getJSONObject()); + } + json.put("events", array); + json.put("idsite", idsite); + json.put("lang", lang); + json.put("ua", ua); + return json.toString(2); + } } private static void addFirstInstallEvent(PackageManager pm, PackageInfo packageInfo) { @@ -354,21 +357,13 @@ public class FDroidMetricsWorker extends Worker { * @see Matomo Event Tracking */ @SuppressWarnings("checkstyle:MemberName") - @JsonInclude(JsonInclude.Include.NON_EMPTY) static class MatomoEvent { - @JsonProperty String category; - @JsonProperty String action; - @JsonProperty String name; - @JsonProperty final long period_start; - @JsonProperty final long period_end; - @JsonProperty long times = 0; - @JsonProperty String value; MatomoEvent(long timestamp) { @@ -384,6 +379,18 @@ public class FDroidMetricsWorker extends Worker { times = 1; } + private JSONObject getJSONObject() throws JSONException { + JSONObject json = new JSONObject(); + json.put("category", category); + json.put("action", action); + json.put("name", name); + json.put("period_start", period_start); + json.put("period_end", period_end); + json.put("times", times); + json.put("value", value); + return json; + } + @Override public boolean equals(Object o) { if (this == o) return true;