From ba0cbd2d7270eb28458af583d9b3fa88bcc09445 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Fri, 8 Dec 2017 14:53:38 +0700 Subject: [PATCH] First functional iteration of the .kmp processor. --- android/KMEA/app/build.gradle | 1 + .../kmea/packages/PackageProcessor.java | 75 ++++++++++++------- .../kmea/packages/PackageProcessorTest.java | 51 ++++++++----- 3 files changed, 81 insertions(+), 46 deletions(-) diff --git a/android/KMEA/app/build.gradle b/android/KMEA/app/build.gradle index db826938c7..541eac95e9 100644 --- a/android/KMEA/app/build.gradle +++ b/android/KMEA/app/build.gradle @@ -43,6 +43,7 @@ android { dependencies { implementation 'com.android.support:support-v4:25.4.0' + implementation 'commons-io:commons-io:2.6' testImplementation 'junit:junit:4.12' testImplementation "org.robolectric:robolectric:3.5.1" } diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/packages/PackageProcessor.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/packages/PackageProcessor.java index 2194bc512f..bd37ce5bdf 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/packages/PackageProcessor.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/packages/PackageProcessor.java @@ -1,5 +1,8 @@ package com.tavultesoft.kmea.packages; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + import com.tavultesoft.kmea.KMManager; import com.tavultesoft.kmea.JSONParser; @@ -17,6 +20,7 @@ import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; +import org.apache.commons.io.FileUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -66,22 +70,9 @@ public class PackageProcessor { } } - static boolean clearDirectory(File path) { - // Java won't allow deleting non-empty directories, so we need recursion to perform a full delete. - if(path.isDirectory()) { - File[] children = path.listFiles(); - - for(File child:children) { - boolean resultFlag = clearDirectory(child); - if(!resultFlag) { - return false; - } - } - } - - return path.delete(); - } - + // A default, managed mapping for package installation, handling both temp directory + // and perm directory locations. No need to relocate the downloaded .kmp file itself. + @NonNull static File constructPath(File path, boolean temp) { String filename = path.getName(); String kmpBaseName; @@ -149,25 +140,55 @@ public class PackageProcessor { return json.getJSONObject("system").getString("fileVersion"); } + // Returns 1 if newer, 0 if equal, and -1 if older or invalid. If no prior version exists, returns 1. + public static int comparePackageDirectories(File newPath, File oldPath) throws IOException, JSONException { + JSONObject newInfoJSON = loadPackageInfo(newPath); + String newVersion = getVersion(newInfoJSON); + + if(oldPath.exists()) { + JSONObject oldInfoJSON = loadPackageInfo(oldPath); + String originalVersion = getVersion(oldInfoJSON); + + if(KMManager.compareVersions(newVersion, originalVersion) == 1) { + return 1; + } else if(KMManager.compareVersions(newVersion, originalVersion) == 0){ + return 0; + } else { + return -1; + } + } else { + return 1; + } + } + + @Nullable public static List> processKMP(File path) throws IOException, JSONException { File tempPath = unzipKMP(path); JSONObject newInfoJSON = loadPackageInfo(tempPath); - String newVersion = getVersion(newInfoJSON); File permPath = constructPath(path, false); if(permPath.exists()) { - JSONObject oldInfoJSON = loadPackageInfo(permPath); - String originalVersion = getVersion(oldInfoJSON); - - // TODO: Compare versions. - // if(newer) then overwrite - // else cancel package install, erase temp directory - return null; - } else { - // No version conflict! Proceed with the install! - // Is within else 'cause there's no need to overwrite. + if(comparePackageDirectories(tempPath, permPath) != -1) { + // Abort! The current installation is newer or as up-to-date. + FileUtils.deleteDirectory(tempPath); + return null; + } else { + // Out with the old. "In with the new" is identical to a new package installation. + FileUtils.deleteDirectory(permPath); + } } + // No version conflict! Proceed with the install! + // A nice, recursive method provided by Apache Commons-IO's FileUtils class. + FileUtils.moveDirectory(tempPath, permPath); + + +// How to retrieve other interesting bits of JSON, with pretty-printing: +// System.out.println("System: " + json.getJSONObject("system").toString(2)); +// System.out.println("Options: " + json.getJSONObject("options").toString(2)); +// System.out.println("Info: " + json.getJSONObject("info").toString(2)); +// System.out.println("Files: " + json.getJSONArray("files").toString(2)); + // newInfoJSON holds all the newly downloaded/updated keyboard data. JSONArray keyboards = newInfoJSON.getJSONArray("keyboards"); ArrayList> keyboardSpecs = new ArrayList<>(); diff --git a/android/KMEA/app/src/test/java/com/tavultesoft/kmea/packages/PackageProcessorTest.java b/android/KMEA/app/src/test/java/com/tavultesoft/kmea/packages/PackageProcessorTest.java index f67c011370..31b20cedbb 100644 --- a/android/KMEA/app/src/test/java/com/tavultesoft/kmea/packages/PackageProcessorTest.java +++ b/android/KMEA/app/src/test/java/com/tavultesoft/kmea/packages/PackageProcessorTest.java @@ -2,9 +2,12 @@ package com.tavultesoft.kmea.packages; import com.tavultesoft.kmea.KMManager; +import org.apache.commons.io.FileUtils; import org.json.JSONObject; +import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -23,6 +26,8 @@ public class PackageProcessorTest { public static final String TEST_GFF_KMP_NAME = "gff_amh_7_test_json"; public static final File TEST_GFF_KMP_FILE = new File(TEST_RESOURCE_ROOT, TEST_GFF_KMP_NAME + ".kmp"); + public static final File TEST_GFF_KMP_TARGET = new File(TEST_EXTRACTION_ROOT, "packages" + + File.separator + TEST_GFF_KMP_NAME); /* TODO: Create an alternate version with a different package version; perform package overwrite tests * in both directions. @@ -30,8 +35,8 @@ public class PackageProcessorTest { private static File tempPkg; - @BeforeClass - public static void extractTestPackages() { + @Before + public void extractTestPackages() { PackageProcessor.initialize(TEST_EXTRACTION_ROOT); try { @@ -53,20 +58,20 @@ public class PackageProcessorTest { JSONObject json = PackageProcessor.loadPackageInfo(tempPkg); Assert.assertNotNull(json); - - // Test pretty-print, for visual inspection if desired. - System.out.println(); - System.out.println("Package version: " + json.getJSONObject("system").get("fileVersion")); - System.out.println(); - System.out.println("System: " + json.getJSONObject("system").toString(2)); - System.out.println(); - System.out.println("Options: " + json.getJSONObject("options").toString(2)); - System.out.println(); - System.out.println("Info: " + json.getJSONObject("info").toString(2)); - System.out.println(); - System.out.println("Files: " + json.getJSONArray("files").toString(2)); - System.out.println(); - System.out.println("Keyboards: " + json.getJSONArray("keyboards").toString(2)); +// +// // Test pretty-print, for visual inspection if desired. +// System.out.println(); +// System.out.println("Package version: " + json.getJSONObject("system").get("fileVersion")); +// System.out.println(); +// System.out.println("System: " + json.getJSONObject("system").toString(2)); +// System.out.println(); +// System.out.println("Options: " + json.getJSONObject("options").toString(2)); +// System.out.println(); +// System.out.println("Info: " + json.getJSONObject("info").toString(2)); +// System.out.println(); +// System.out.println("Files: " + json.getJSONArray("files").toString(2)); +// System.out.println(); +// System.out.println("Keyboards: " + json.getJSONArray("keyboards").toString(2)); } @Test @@ -109,8 +114,16 @@ public class PackageProcessorTest { Assert.assertNotEquals(new File(permPath), PackageProcessor.constructPath(TEST_GFF_KMP_FILE, true)); } - @AfterClass - public static void eraseTestPackages() { - PackageProcessor.clearDirectory(tempPkg); + @Test + public void test_installKMP() throws Exception { + PackageProcessor.processKMP(TEST_GFF_KMP_FILE); + + Assert.assertTrue(TEST_GFF_KMP_TARGET.exists()); + } + + @After + public void eraseTestPackages() throws IOException { + FileUtils.deleteDirectory(tempPkg); + FileUtils.deleteDirectory(TEST_GFF_KMP_TARGET); } } \ No newline at end of file