From 66781d6352739db5980fd01fc72ef7e916f85f5f Mon Sep 17 00:00:00 2001 From: shenzhenfang Date: Mon, 30 Oct 2023 16:49:30 +0800 Subject: [PATCH] add hapaddition mode --- adapter/ohos/CompressVerify.java | 55 +++++++++ adapter/ohos/Compressor.java | 205 ++++++++++++++++++++++++++++--- adapter/ohos/Uncompress.java | 30 +++++ adapter/ohos/Utility.java | 13 ++ 4 files changed, 284 insertions(+), 19 deletions(-) diff --git a/adapter/ohos/CompressVerify.java b/adapter/ohos/CompressVerify.java index eeda7375..0b5bd785 100644 --- a/adapter/ohos/CompressVerify.java +++ b/adapter/ohos/CompressVerify.java @@ -50,9 +50,11 @@ public class CompressVerify { private static final String HQF_SUFFIX = ".hqf"; private static final String APPQF_SUFFIX = ".appqf"; private static final String HSP_SUFFIX = ".hsp"; + private static final String JSON_SUFFIX = ".json"; private static final String FALSE = "false"; private static final String ENTRY_CARD_DIRECTORY_NAME = "EntryCard"; private static final String VERSION_NAME_PATTERN = "^[0-9.]+|(?=.*[{])(?=.*[}])[0-9a-zA-Z_.{}]+$"; + private static final String LINUX_FILE_SEPARATOR = "/"; private static final Log LOG = new Log(CompressVerify.class.toString()); @@ -108,6 +110,8 @@ public class CompressVerify { return isVerifyValidInAPPQFMode(utility); case Utility.MODE_HSP: return isVerifyValidInHspMode(utility); + case Utility.MODE_HAPADDITION: + return isVerifyValidInHapAdditionMode(utility); case Utility.VERSION_NORMALIZE: return validateVersionNormalizeMode(utility); default: @@ -810,6 +814,57 @@ public class CompressVerify { return isOutPathValid(utility, HSP_SUFFIX); } + private static boolean isVerifyValidInHapAdditionMode(Utility utility) { + if (utility.getHapPath().isEmpty()) { + LOG.error("CompressVerify::isVerifyValidInHapAdditionMode hapPath is empty."); + return false; + } + String hapPath = utility.getAbsoluteHapPath(); + File hapFile = new File(hapPath); + if (hapFile.isDirectory()) { + LOG.error("CompressVerify::isVerifyValidInHapAdditionMode hapPath cannot be a folder."); + return false; + } + if (!(hapPath.endsWith(HAP_SUFFIX) || hapPath.endsWith(HSP_SUFFIX))) { + LOG.error("CompressVerify::isVerifyValidInHapAdditionMode hapPath is invalid."); + return false; + } + if (!hapFile.exists()) { + LOG.error("CompressVerify::isVerifyValidInHapAdditionMode hap file does not exist."); + return false; + } + if (utility.getJsonPath().isEmpty()) { + LOG.error("CompressVerify::isVerifyValidInHapAdditionMode jsonPath is empty."); + return false; + } + if (!utility.getJsonPath().endsWith(JSON_SUFFIX)) { + LOG.error("CompressVerify::isVerifyValidInHapAdditionMode jsonPath is invalid."); + return false; + } + File jsonFile = new File(utility.getJsonPath()); + if (!jsonFile.exists()) { + LOG.error("CompressVerify::isVerifyValidInHapAdditionMode json file does not exist."); + return false; + } + if (utility.getOutPath().isEmpty()) { + LOG.error("CompressVerify::isVerifyValidInHapAdditionMode outPath is empty."); + return false; + } + if (utility.getOutPath().contains(".")) { + LOG.error("CompressVerify::isVerifyValidInHapAdditionMode outPath is file."); + return false; + } + File absoluteHapFile = new File(utility.getAbsoluteHapPath()); + String hapFileName = absoluteHapFile.getName(); + String destPath = utility.getOutPath() + LINUX_FILE_SEPARATOR + hapFileName;; + File destFile = new File(destPath); + if ("false".equals(utility.getForceRewrite()) && destFile.exists()) { + LOG.error("CompressVerify::isVerifyValidInHapAdditionMode target file already exists."); + return false; + } + return true; + } + private static boolean isSharedApp(Utility utility) { if (!utility.getHapPath().isEmpty()) { return false; diff --git a/adapter/ohos/Compressor.java b/adapter/ohos/Compressor.java index f4010bda..54881562 100644 --- a/adapter/ohos/Compressor.java +++ b/adapter/ohos/Compressor.java @@ -15,18 +15,7 @@ package ohos; -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; +import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -34,13 +23,7 @@ import java.nio.file.Paths; import java.nio.file.attribute.FileTime; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Optional; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.CRC32; @@ -65,6 +48,7 @@ public class Compressor { private static final String CONFIG_JSON = "config.json"; private static final String MODULE_JSON = "module.json"; private static final String PATCH_JSON = "patch.json"; + private static final String ADDITION_JSON = "addition.json"; private static final String NAME = "name"; private static final String NULL_DIR_NAME = ""; private static final String RES_DIR_NAME = "res/"; @@ -135,6 +119,10 @@ public class Compressor { private static final String ASSETS_FILE_NAME = "assets"; private static final String MAPLE_FILE_NAME = "maple"; private static final String SHARED_LIBS_FILE_NAME = "shared_libs"; + private static final String HAPADDITION_FOLDER_NAME = "hapAddition"; + private static final String TARGET_FILE_PATH = HAPADDITION_FOLDER_NAME + LINUX_FILE_SEPARATOR + "resources" + + LINUX_FILE_SEPARATOR + "base" + LINUX_FILE_SEPARATOR + "profile"; + private static final String BACKUP_PREFIX = "backup"; // set timestamp to get fixed MD5 private static final long FILE_TIME = 1546272000000L; @@ -302,6 +290,10 @@ public class Compressor { versionNormalize(utility); return true; } + if (Utility.MODE_HAPADDITION.equals(utility.getMode())) { + HapAddition(utility); + return true; + } File destFile = new File(utility.getOutPath()); // if out file directory not exist, mkdirs. @@ -1106,6 +1098,181 @@ public class Compressor { } } + /** + * compress in hapAddition mode. + * + * @param utility common data + * @throws BundleException FileNotFoundException|IOException. + */ + private void HapAddition(Utility utility) { + File hapPath = new File(utility.getAbsoluteHapPath()); + String hapFileName = hapPath.getName(); + File hapParentPath = hapPath.getParentFile(); + File outPath = new File(utility.getOutPath()); + File destFile; + if (!Objects.equals(hapParentPath, outPath)) { + destFile = new File(utility.getOutPath() + LINUX_FILE_SEPARATOR + hapFileName); + } else { + destFile = new File(hapFileName); + } + File outParentFile = destFile.getParentFile(); + if ((outParentFile != null) && (!outParentFile.exists())) { + if (!outParentFile.mkdirs()) { + LOG.error("Compressor::compressProcess create out file parent directory failed."); + } + } + FileOutputStream fileOut = null; + CheckedOutputStream checkedOut = null; + try { + String backName = BACKUP_PREFIX + hapFileName; + copyHapFile(utility, backName); + fileOut = new FileOutputStream(destFile); + checkedOut = new CheckedOutputStream(fileOut, new CRC32()); + zipOut = new ZipOutputStream(checkedOut); + compressHapAddition(utility); + deleteFile(backName); + } catch (FileNotFoundException exception) { + LOG.error("Compressor::HapAddition hapFile not found exception" + exception.getMessage()); + } catch (BundleException ignored) { + LOG.error("Compressor::HapAddition Bundle exception."); + } catch (IOException exception) { + LOG.error("Compressor::HapAddition IO exception."); + } finally { + closeZipOutputStream(); + Utility.closeStream(zipOut); + Utility.closeStream(checkedOut); + Utility.closeStream(fileOut); + } + } + + private void copyHapFile(Utility utility, String backName) throws IOException, BundleException { + File hapFile = new File(utility.getAbsoluteHapPath()); + String currentDir = System.getProperty("user.dir"); + String backupPath = currentDir+ LINUX_FILE_SEPARATOR + backName; + File backupFile = new File(backupPath); + FileUtils.copyFile(hapFile, backupFile); + utility.setHapPath(backName); + } + + private static String readerFile(String jsonPath) throws IOException { + File jsonFile = new File(jsonPath); + FileReader fileReader = new FileReader(jsonFile); + Reader reader = new InputStreamReader(new FileInputStream(jsonFile), "Utf-8"); + int ch= 0; + StringBuffer sb = new StringBuffer(); + while((ch = reader.read()) != -1) { + sb.append((char) ch); + } + fileReader.close(); + reader.close(); + return sb.toString(); + } + + private static void writeJsonFile(String targetPath, JSONObject dataJson) throws IOException { + FileWriter fileWriter = new FileWriter(targetPath); + // format json + String pretty = JSON.toJSONString(dataJson, + SerializerFeature.PrettyFormat, + SerializerFeature.WriteMapNullValue); + fileWriter.write(pretty); + fileWriter.flush(); + fileWriter.close(); + } + + private static void setUtilityParameter(String hapAdditionPath, Utility utility) throws IOException { + Files.walk(Path.of(hapAdditionPath), 1).forEach(path -> { + String fileName = path.getFileName().toString(); + String filePath = path.toString(); + switch (fileName) { + case ETS_FILE_NAME: + utility.setEtsPath(filePath); + break; + case DIR_FILE_NAME: + utility.setLibPath(filePath); + break; + case AN_FILE_NAME: + utility.setANPath(filePath); + break; + case AP_FILE_NAME: + utility.setAPPath(filePath); + break; + case RESOURCE_FILE_NAME: + utility.setResourcesPath(filePath); + break; + case JS_FILE_NAME: + utility.setJsPath(filePath); + break; + case ASSETS_FILE_NAME: + utility.setAssetsPath(filePath); + break; + case MAPLE_FILE_NAME: + utility.setSoDir(filePath); + break; + case SHARED_LIBS_FILE_NAME: + utility.setSharedLibsPath(filePath); + break; + case MODULE_JSON: + utility.setJsonPath(filePath); + break; + case RES_INDEX: + utility.setIndexPath(filePath); + break; + case PACKINFO_NAME: + utility.setPackInfoPath(filePath); + break; + } + }); + } + + private void compressHapAddition(Utility utility) throws BundleException, IOException { + // decompression hap file to hapAddition + String currentDir = System.getProperty("user.dir"); + String oldOutPath = utility.getOutPath(); + String hapAdditionPath = currentDir+ LINUX_FILE_SEPARATOR + HAPADDITION_FOLDER_NAME; + utility.setOutPath(hapAdditionPath); + Uncompress.unpackageProcess(utility); + utility.setOutPath(oldOutPath); + + // generate addition.json file + try { + String data = readerFile(utility.getJsonPath()); + JSONObject dataJson = JSONObject.parseObject(data); + String targetParentPath = currentDir + LINUX_FILE_SEPARATOR + TARGET_FILE_PATH; + File targetParent = new File(targetParentPath); + if (!targetParent.exists()) { + if (!targetParent.mkdirs()) { + LOG.error("Compressor::compressHapAddition create target file parent directory failed."); + } + } + String targetPath = targetParentPath + LINUX_FILE_SEPARATOR + ADDITION_JSON; + writeJsonFile(targetPath, dataJson); + } catch (IOException e) { + String errMsg = "Compressor::compressHapAddition jsonfile failed."; + LOG.error(errMsg); + throw new BundleException(errMsg); + } + + // package a new hap file + try { + setUtilityParameter(hapAdditionPath, utility); + } catch (IOException e) { + String errMsg = "Compressor::compressHapAddition setUtilityParameter failed."; + LOG.error(errMsg); + throw new BundleException(errMsg); + } + if (utility.getHapPath().endsWith(HAP_SUFFIX)) { + compressHap(utility); + } else if (utility.getHapPath().endsWith(HSP_SUFFIX)) { + compressHsp(utility); + } else { + String errMsg = "Compressor::compressHapAddition compressFile failed."; + LOG.error(errMsg); + throw new BundleException(errMsg); + } + // delete packaging and unpacking process files + deleteFile(hapAdditionPath); + } + /** * pack hap in app to selectedHaps * diff --git a/adapter/ohos/Uncompress.java b/adapter/ohos/Uncompress.java index c837c8b9..466ef9a5 100644 --- a/adapter/ohos/Uncompress.java +++ b/adapter/ohos/Uncompress.java @@ -122,6 +122,9 @@ public class Uncompress { case Utility.MODE_HSP: dataTransferAllFiles(utility.getHspPath(), utility.getOutPath()); break; + case Utility.MODE_HAPADDITION: + unpackageHapAdditionMode(utility); + break; default: LOG.error("Uncompress::unpackageProcess input wrong type!"); throw new BundleException("Uncompress::unpackageProcess input wrong type!"); @@ -164,6 +167,33 @@ public class Uncompress { throw new BundleException("Uncompress::unpackageHapMode failed"); } } + /** + * unpack hapAddition. + * + * @param utility common data + */ + static void unpackageHapAdditionMode(Utility utility) throws BundleException { + if (!Utility.MODE_HAPADDITION.equals(utility.getMode())) { + throw new BundleException("Uncompress::unpackageHapAdditionMode input wrong unpack mode"); + } + try { + if (TRUE.equals(utility.getRpcid())) { + getRpcidFromHap(utility.getHapPath(), utility.getOutPath()); + return; + } + if (TRUE.equals(utility.getUnpackApk())) { + unzip(utility, utility.getHapPath(), utility.getOutPath(), APK_SUFFIX); + String[] temp = utility.getHapPath().replace("\\", "/").split("/"); + String hapName = temp[temp.length - 1]; + repackHap(utility.getHapPath(), utility.getOutPath(), hapName, utility.getUnpackApk()); + } else { + dataTransferAllFiles(utility.getHapPath(), utility.getOutPath()); + } + } catch (BundleException e) { + LOG.error("Uncompress::unpackageHapMode failed"); + throw new BundleException("Uncompress::unpackageHapMode failed"); + } + } /** * uncompress app. diff --git a/adapter/ohos/Utility.java b/adapter/ohos/Utility.java index 40e8713c..ece2ff19 100644 --- a/adapter/ohos/Utility.java +++ b/adapter/ohos/Utility.java @@ -35,6 +35,7 @@ public class Utility { static final String MODE_APPQF = "appqf"; static final String MODE_RES = "res"; static final String MODE_HSP = "hsp"; + static final String MODE_HAPADDITION = "hapaddition"; static final String VERSION_NORMALIZE = "versionNormalize"; static final String FALSE_STRING = "false"; @@ -94,6 +95,7 @@ public class Utility { private String mainModuleLimit = ""; private String normalModuleLimit = ""; private String totalLimit = ""; + private String absoluteHapPath = ""; private boolean generateBuildHash = false; private boolean buildHashFinish = false; @@ -268,6 +270,7 @@ public class Utility { public void setHapPath(String hapPath) { if (!hapPath.startsWith(CMD_PREFIX)) { this.hapPath = hapPath; + this.absoluteHapPath = getFormattedPath(hapPath); } } @@ -728,6 +731,16 @@ public class Utility { return this.apPath; } + public String getAbsoluteHapPath() { + return this.absoluteHapPath; + } + + public void setAbsoluteHapPath(String absoluteHapPath) { + if (!absoluteHapPath.startsWith(CMD_PREFIX)) { + this.absoluteHapPath = getFormattedPath(absoluteHapPath); + } + } + public void setIsSharedApp(boolean isSharedApp) { this.isSharedApp = isSharedApp; } -- Gitee