diff --git a/.gitignore b/.gitignore
old mode 100644
new mode 100755
index 8b137891791fe96927ad78e64b0aad7bded08bdc..c51f72aea4f1c609fe75a2f4e84acba5846a877b
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
-
+jar
+.idea/
diff --git a/BUILD.gn b/BUILD.gn
index 53804692b44deb6271b1284ba90682dc52bb783b..42c162213bdb2cde7f7fa1a463f0fa75ea7249d0 100755
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -60,6 +60,7 @@ java_library("hmos_app_unpacking_tool_java") {
"com/huawei/ohos/ScreenDensity.java",
"com/huawei/ohos/ScreenWindow.java",
"com/huawei/ohos/CountryCode.java",
+ "com/huawei/ohos/HapZipInfo.java",
]
deps = [ "//third_party/fastjson/repackaged:fastjson_utils_java" ]
diff --git a/README_zh.md b/README_zh.md
new file mode 100644
index 0000000000000000000000000000000000000000..b91aea9a5f1b7103b766eaeaa425d5b1b3e2ce3c
--- /dev/null
+++ b/README_zh.md
@@ -0,0 +1,12 @@
+# 打包工具组件
+
+- [简介](#section11660541593)
+
+## 简介
+
+本组件包含打包、拆包和包解析三个功能模块:
+
+- 打包模块有将资源文件打包成hap包,和将多个hap包打包成app包两种模式。
+- 拆包模块有从app包中拆出所有hap包,和从hap包中拆出json文件两种模式。
+
+- 包解析模块可以根据对应解析模式,解析出指定设备类型下的hap包列表、hap包信息、签名信息等。
\ No newline at end of file
diff --git a/com/huawei/ohos/AppInfo.java b/com/huawei/ohos/AppInfo.java
index 03c89c93afb323488da3f018d82668e99ca7dc6a..278877abc26852ae2eed3a299496efbff49a14c3 100755
--- a/com/huawei/ohos/AppInfo.java
+++ b/com/huawei/ohos/AppInfo.java
@@ -74,4 +74,71 @@ public class AppInfo {
* Indicates the releaseType of app AppInfo.
*/
public String releaseType = "";
+
+
+ private String shellVersionCode = "";
+ private String shellVersionName = "";
+ private boolean multiFrameworkBundle;
+
+ /**
+ * Get shell version code.
+ *
+ * @return shell version code
+ */
+ public String getShellVersionCode() {
+ return shellVersionCode;
+ }
+
+ /**
+ * Set shell version code.
+ *
+ * @param shellVersionCode Indicates the shell version name
+ */
+ public void setShellVersionCode(String shellVersionCode) {
+ this.shellVersionCode = shellVersionCode;
+ }
+
+ /**
+ * Get shell version name.
+ *
+ * @return shell version name
+ */
+ public String getShellVersionName() {
+ return shellVersionName;
+ }
+
+ /**
+ * Set shell version name.
+ *
+ * @param shellVersionName Indicates the shell version name
+ */
+ public void setShellVersionName(String shellVersionName) {
+ this.shellVersionName = shellVersionName;
+ }
+
+ /**
+ * Whether the app is multi framework bundle.
+ *
+ * @return true if the app is a multi framework bundle.
+ */
+ public boolean isMultiFrameworkBundle() {
+ return multiFrameworkBundle;
+ }
+
+ /**
+ * Set multi framework bundle.
+ *
+ * @param multiFrameworkBundle Indicates the app type
+ */
+ public void setMultiFrameworkBundle(boolean multiFrameworkBundle) {
+ this.multiFrameworkBundle = multiFrameworkBundle;
+ }
+
+ /**
+ * Set default shell version
+ */
+ public void setDefaultShellVersion() {
+ this.shellVersionCode = versionCode;
+ this.shellVersionName = versionName;
+ }
}
diff --git a/com/huawei/ohos/CommandParser.java b/com/huawei/ohos/CommandParser.java
index fc31819929c0f27e00f79b7d07b06ca08dd2f34a..7351061e88263b5263a8aee4a464d31608a462c0 100755
--- a/com/huawei/ohos/CommandParser.java
+++ b/com/huawei/ohos/CommandParser.java
@@ -40,7 +40,7 @@ public class CommandParser {
private static final String CMD_SO_DIR = "--maple-so-dir";
private static final String CMD_ABILITY_SO_PATH = "--ability-so-path";
private static final String CMD_DEX_PATH = "--dex-path";
- private static final String CMD_AEX_PATH = "--aex-path";
+ private static final String CMD_ABC_PATH = "--abc-path";
private static final String CMD_LIB_PATH = "--lib-path";
private static final String CMD_RES_PATH = "--res-path";
private static final String CMD_RESOURCES_PATH = "--resources-path";
@@ -255,8 +255,8 @@ public class CommandParser {
utility.setDexPath(value);
return true;
}
- case CMD_AEX_PATH: {
- utility.setAexPath(value);
+ case CMD_ABC_PATH: {
+ utility.setAbcPath(value);
return true;
}
case CMD_LIB_PATH: {
diff --git a/com/huawei/ohos/CompressVerify.java b/com/huawei/ohos/CompressVerify.java
index 1e3602821185ca44be1717c402203125e7b081f1..06f1ba7be029b8562c65707e7f7c8665df263403 100755
--- a/com/huawei/ohos/CompressVerify.java
+++ b/com/huawei/ohos/CompressVerify.java
@@ -38,7 +38,7 @@ public class CompressVerify {
private static final String APP_SUFFIX = ".app";
private static final String APK_SUFFIX = ".apk";
private static final String DEX_SUFFIX = ".dex";
- private static final String AEX_SUFFIX = ".aex";
+ private static final String ABC_SUFFIX = ".abc";
private static final String SO_SUFFIX = ".so";
private static final String JAR_SUFFIX = ".jar";
private static final String TXT_SUFFIX = ".txt";
@@ -107,9 +107,9 @@ public class CompressVerify {
return false;
}
- if (!utility.getAexPath().isEmpty() && !compatibleProcess(utility, utility.getAexPath(),
- utility.getFormattedAexPathList(), AEX_SUFFIX)) {
- LOG.error("CompressVerify::isArgsValidInHapMode aex-path is invalid!");
+ if (!utility.getAbcPath().isEmpty() && !compatibleProcess(utility, utility.getAbcPath(),
+ utility.getFormattedAbcPathList(), ABC_SUFFIX)) {
+ LOG.error("CompressVerify::isArgsValidInHapMode abc-path is invalid!");
return false;
}
diff --git a/com/huawei/ohos/Compressor.java b/com/huawei/ohos/Compressor.java
index cc17acbc79ad6ee2409bbee8b7aa34ebf2be7d5a..cd5022aee170efda550d38659651676ff3bc476f 100755
--- a/com/huawei/ohos/Compressor.java
+++ b/com/huawei/ohos/Compressor.java
@@ -41,6 +41,7 @@ import java.util.zip.ZipOutputStream;
import java.util.Enumeration;
import java.util.ArrayList;
import java.util.List;
+import java.util.Arrays;
/**
* bundle compressor class, compress file and directory.
@@ -110,8 +111,9 @@ public class Compressor {
private ZipOutputStream zipOut = null;
private List list = new ArrayList();
- private List fromsList = new ArrayList();
+ private List formNamesList = new ArrayList();
private List fileNameList = new ArrayList();
+ private List supportDimensionsList = Arrays.asList(PIC_1X2, PIC_2X4, PIC_4X4);
/**
* start compress.
@@ -246,8 +248,8 @@ public class Compressor {
pathToFile(utility, dexPathItem, NULL_DIR_NAME, false);
}
- for (String aexPathItem : utility.getFormattedAexPathList()) {
- pathToFile(utility, aexPathItem, NULL_DIR_NAME, false);
+ for (String abcPathItem : utility.getFormattedAbcPathList()) {
+ pathToFile(utility, abcPathItem, NULL_DIR_NAME, false);
}
for (String apkPathItem : utility.getFormattedApkPathList()) {
@@ -318,12 +320,20 @@ public class Compressor {
pathToFile(utility, utility.getSignaturePath(), NULL_DIR_NAME, false);
}
- String[] outPath = utility.getOutPath().split("\\\\");
+ String[] outPath = utility.getOutPath().replace("\\", "/").split("/");
+ if (outPath.length < 2) {
+ LOG.error("Compressor::compressAppMode the outPath is invalid, length: " + outPath.length);
+ return;
+ }
String[] path = utility.getOutPath().split(outPath[outPath.length - 2].toString());
List fileList = new ArrayList<>();
for (String hapPathItem : utility.getFormattedHapPathList()) {
String fName = hapPathItem.trim();
- String[] temp = fName.split("\\\\");
+ String[] temp = fName.replace("\\", "/").split("/");
+ if (temp.length < 1) {
+ LOG.error("Compressor::compressAppMode the hap file path is invalid, length: " + temp.length);
+ continue;
+ }
String[] str = temp[temp.length - 1].split("\\.");
String outPathString = path[0] + str[0];
fileList.add(outPathString);
@@ -376,6 +386,7 @@ public class Compressor {
}
outputStream = new FileOutputStream(destFile);
out = new ZipOutputStream(new CheckedOutputStream(outputStream, new CRC32()));
+ out.setMethod(ZipOutputStream.STORED);
compress(new File(path), out, NULL_DIR_NAME, true);
} catch (FileNotFoundException ignored) {
LOG.error("zip file not found exception");
@@ -542,7 +553,12 @@ public class Compressor {
for (String fileName : fileNameList) {
if (fileName.endsWith(PNG_SUFFIX) || fileName.endsWith(UPPERCASE_PNG_SUFFIX)) {
String fName = fileName.trim();
- String[] temp = fName.split("\\\\");
+ String[] temp = fName.replace("\\", "/").split("/");
+ if (temp.length < 4) {
+ LOG.error("Compressor::compressPackResMode the hap file path is invalid, length: "
+ + temp.length);
+ continue;
+ }
String fileModelName = temp[temp.length - 4];
if (!isModelName(fileModelName)) {
LOG.error("Compressor::compressProcess compress failed ModelName Error!");
@@ -634,26 +650,22 @@ public class Compressor {
if (name == null || name.isEmpty()) {
return isSpecifications;
}
- if (name.endsWith(PNG_SUFFIX) || name.endsWith(UPPERCASE_PNG_SUFFIX)) {
- String[] picName = name.split("-");
- if (picName.length > 1) {
- for (String fromName : fromsList) {
- if (fromName.equals(picName[0])) {
- isSpecifications = false;
- String[] normName = picName[1].split("\\.");
- if (normName[0].equals( PIC_1X2 ) || normName[0].equals( PIC_2X2 )
- || normName[0].equals( PIC_2X4 ) || normName[0].equals( PIC_4X4 )) {
- isSpecifications = true;
- }
- }
- }
- return isSpecifications;
- } else {
- return isSpecifications;
- }
- } else {
- return isSpecifications;
+ if (!name.endsWith(PNG_SUFFIX) && !name.endsWith(UPPERCASE_PNG_SUFFIX)) {
+ LOG.error("isPicturing: the suffix is not .png or .PNG");
+ return false;
+ }
+ int delimiterIndex = name.lastIndexOf("-");
+ if (delimiterIndex < 0) {
+ LOG.error("isPicturing: the entry card naming format is invalid and should be separated by '-'!");
+ return false;
+ }
+ String formName = name.substring(0, delimiterIndex);
+ if (!formNamesList.contains(formName)) {
+ LOG.error("isPicturing: the name is not same as formName, name: " + formName);
+ return false;
}
+ String dimension = name.substring(delimiterIndex + 1, name.lastIndexOf("."));
+ return supportDimensionsList.contains(dimension);
}
/**
@@ -676,6 +688,10 @@ public class Compressor {
for (File f : files) {
try {
if (f.isFile()) {
+ if (f.getName().endsWith(".DS_Store")) {
+ deleteFile(f.getCanonicalPath());
+ continue;
+ }
fileNameList.add(f.getCanonicalPath());
} else if (f.isDirectory()) {
getFileList(f.getCanonicalPath());
@@ -755,13 +771,14 @@ public class Compressor {
* @param name filename
* @param KeepDirStructure Empty File
*/
- private static void compress(File sourceFile, ZipOutputStream zos, String name,
+ private void compress(File sourceFile, ZipOutputStream zos, String name,
boolean KeepDirStructure) {
FileInputStream in = null;
try {
byte[] buf = new byte[BUFFER_SIZE];
if (sourceFile.isFile()) {
- zos.putNextEntry(new ZipEntry(name));
+ ZipEntry zipEntry = getStoredZipEntry(sourceFile, name);
+ zos.putNextEntry(zipEntry);
in = new FileInputStream(sourceFile);
int len;
while ((len = in.read(buf)) != -1) {
@@ -773,9 +790,11 @@ public class Compressor {
if (listFiles == null || listFiles.length == 0) {
if (KeepDirStructure) {
if (!name.isEmpty()) {
- zos.putNextEntry(new ZipEntry(name + "/"));
+ ZipEntry zipEntry = getStoredZipEntry(sourceFile, name + "/");
+ zos.putNextEntry(zipEntry);
} else {
- zos.putNextEntry(new ZipEntry(name));
+ ZipEntry zipEntry = getStoredZipEntry(sourceFile, name);
+ zos.putNextEntry(zipEntry);
}
zos.closeEntry();
}
@@ -793,11 +812,50 @@ public class Compressor {
LOG.error("Compressor::compressFile file not found exception");
} catch (IOException exception) {
LOG.error("Compressor::compressFile io exception: " + exception.getMessage());
- }finally {
+ } catch (BundleException bundleException) {
+ LOG.error("Compressor::compressFile bundle exception" + bundleException.getMessage());
+ } finally {
Utility.closeStream(in);
}
}
+ private ZipEntry getStoredZipEntry(File sourceFile, String name) throws BundleException {
+ ZipEntry zipEntry = new ZipEntry(name);
+ zipEntry.setMethod(ZipEntry.STORED);
+ zipEntry.setCompressedSize(sourceFile.length());
+ zipEntry.setSize(sourceFile.length());
+ CRC32 crc = getCrcFromFile(sourceFile);
+ zipEntry.setCrc(crc.getValue());
+ FileTime fileTime = FileTime.fromMillis(FILE_TIME);
+ zipEntry.setLastAccessTime(fileTime);
+ zipEntry.setLastModifiedTime(fileTime);
+ return zipEntry;
+ }
+
+ private CRC32 getCrcFromFile(File file) throws BundleException {
+ FileInputStream fileInputStream = null;
+ CRC32 crc = new CRC32();
+ try {
+ fileInputStream = new FileInputStream(file);
+ byte[] buffer = new byte[BUFFER_SIZE];
+
+ int count = fileInputStream.read(buffer);
+ while (count > 0) {
+ crc.update(buffer, 0, count);
+ count = fileInputStream.read(buffer);
+ }
+ } catch (FileNotFoundException ignored) {
+ LOG.error("Uncompressor::getCrcFromFile file not found exception");
+ throw new BundleException("Get Crc from file failed");
+ } catch (IOException exception) {
+ LOG.error("Uncompressor::getCrcFromFile io exception: " + exception.getMessage());
+ throw new BundleException("Get Crc from file failed");
+ } finally {
+ Utility.closeStream(fileInputStream);
+ }
+ return crc;
+ }
+
/**
* isNameEmpty
*
@@ -806,7 +864,7 @@ public class Compressor {
* @param KeepDirStructure KeepDirStructure
* @param file file
*/
- private static void isNameEmpty(ZipOutputStream zos, String name, boolean KeepDirStructure, File file) {
+ private void isNameEmpty(ZipOutputStream zos, String name, boolean KeepDirStructure, File file) {
if (!name.isEmpty()) {
compress(file, zos, name + "/" + file.getName(), KeepDirStructure);
} else {
@@ -1309,7 +1367,7 @@ public class Compressor {
}
String[] nameList = fromsName.split("\\.");
if (nameList.length <= 1) {
- fromsList.add(fromsName);
+ formNamesList.add(fromsName);
}
} catch (StringIndexOutOfBoundsException exception) {
LOG.error("Compressor::parseModuleName field module-name is fault: " + exception.getMessage());
diff --git a/com/huawei/ohos/HapZipInfo.java b/com/huawei/ohos/HapZipInfo.java
new file mode 100755
index 0000000000000000000000000000000000000000..5e26f5c003dadaab855d38a3fce04d6440ec580d
--- /dev/null
+++ b/com/huawei/ohos/HapZipInfo.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.huawei.ohos;
+
+/**
+ * Hap zip info
+ *
+ * @author yaoyanbing
+ * @since 2021-03-16
+ */
+class HapZipInfo {
+ private byte[] resDataBytes;
+ private String harmonyProfileJsonStr = "";
+ private String packInfoJsonStr = "";
+ private String hapFileName = "";
+
+ /**
+ * Get resource data bytes.
+ *
+ * @return resource data bytes.
+ */
+ public byte[] getResDataBytes() {
+ return resDataBytes;
+ }
+
+ /**
+ * Set resource data bytes.
+ *
+ * @param resDataBytes Indicates the resource data bytes.
+ */
+ public void setResDataBytes(byte[] resDataBytes) {
+ this.resDataBytes = resDataBytes;
+ }
+
+ /**
+ * Get harmony profile json string.
+ *
+ * @return harmony profile json string.
+ */
+ public String getHarmonyProfileJsonStr() {
+ return harmonyProfileJsonStr;
+ }
+
+ /**
+ * Set harmony profile json string.
+ *
+ * @param harmonyProfileJsonStr Indicates harmony profile json string.
+ */
+ public void setHarmonyProfileJsonStr(String harmonyProfileJsonStr) {
+ this.harmonyProfileJsonStr = harmonyProfileJsonStr;
+ }
+
+ /**
+ * Get pack.info json string.
+ *
+ * @return pack.info json string.
+ */
+ public String getPackInfoJsonStr() {
+ return packInfoJsonStr;
+ }
+
+ /**
+ * Set pack.info json string.
+ *
+ * @param packInfoJsonStr Indicates the pack.info json string.
+ */
+ public void setPackInfoJsonStr(String packInfoJsonStr) {
+ this.packInfoJsonStr = packInfoJsonStr;
+ }
+
+ /**
+ * Get hap file name.
+ *
+ * @return hap file name.
+ */
+ public String getHapFileName() {
+ return hapFileName;
+ }
+
+ /**
+ * Set hap file name.
+ *
+ * @param hapFileName Indicates the hap file name.
+ */
+ public void setHapFileName(String hapFileName) {
+ this.hapFileName = hapFileName;
+ }
+}
diff --git a/com/huawei/ohos/JsonUtil.java b/com/huawei/ohos/JsonUtil.java
index d8aa3a87d067bcae46dab6e82b2aba7b7c4994cc..40ced5982e000c2fad2285de6d2bfdf6d439159f 100755
--- a/com/huawei/ohos/JsonUtil.java
+++ b/com/huawei/ohos/JsonUtil.java
@@ -42,6 +42,13 @@ public class JsonUtil {
private static final String ASSETS_DIR_NAME = "assets/";
private static final Log LOG = new Log(JsonUtil.class.toString());
+ private static final String SUMMARY = "summary";
+ private static final String APP = "app";
+ private static final String VERSION = "version";
+ private static final String LEGACY_VERSION_CODE = "legacyVersionCode";
+ private static final String LEGACY_VERSION_NAME = "legacyVersionName";
+ private static final String MULTI_FRAMEWORK_BUNDLE = "multiFrameworkBundle";
+
/**
* parse hap list by device type
*
@@ -89,24 +96,64 @@ public class JsonUtil {
return packInfos;
}
+ private static boolean parseShellVersionInfoToAppInfo(String packInfoJsonStr, AppInfo appInfo) {
+ LOG.info("Uncompress::parseShellVersionInfoToAppInfo: begin");
+ if (!appInfo.isMultiFrameworkBundle()) {
+ LOG.info("Uncompress::parseShellVersionInfoToAppInfo: is not a multi framewok bundle.");
+ return false;
+ }
+
+ JSONObject jsonObject = JSONObject.parseObject(packInfoJsonStr);
+ if (jsonObject == null) {
+ LOG.error("Uncompress::parseShellVersionInfoToAppInfo error: summary is null");
+ return false;
+ }
+
+ JSONObject summaryJson = jsonObject.getJSONObject(SUMMARY);
+ if (summaryJson == null) {
+ LOG.error("Uncompress::parseShellVersionInfoToAppInfo error: summary is null");
+ return false;
+ }
+ JSONObject appJson = summaryJson.getJSONObject(APP);
+ if (appJson == null) {
+ LOG.error("Uncompress::parseShellVersionInfoToAppInfo error: app is null");
+ return false;
+ }
+ JSONObject versionJson = appJson.getJSONObject(VERSION);
+ if (versionJson == null) {
+ LOG.error("Uncompress::parseShellVersionInfoToAppInfo error: version is null");
+ return false;
+ }
+
+ if (!versionJson.containsKey(LEGACY_VERSION_CODE) || !versionJson.containsKey(LEGACY_VERSION_NAME)) {
+ LOG.error("Uncompress::parseShellVersionInfoToAppInfo no legacy version info.");
+ return false;
+ }
+ appInfo.setShellVersionCode(versionJson.getString(LEGACY_VERSION_CODE));
+ appInfo.setShellVersionName(versionJson.getString(LEGACY_VERSION_NAME));
+ return true;
+ }
+
/**
* parse hap profile info
*
- * @param jsonString uncompress json String
+ * @param harmonyProfileJsonString uncompress json String
* @param data resource index data
+ * @param paclInfoJsonString pack.info json String
* @return the parseProfileInfo result
* @throws BundleException Throws this exception if the json is not standard.
*/
- static ProfileInfo parseProfileInfo(String jsonString, byte[] data) throws BundleException {
+ static ProfileInfo parseProfileInfo(String harmonyProfileJsonString, byte[] data, String paclInfoJsonString)
+ throws BundleException {
ProfileInfo profileInfo = new ProfileInfo();
- JSONObject jsonObject = JSONObject.parseObject(jsonString);
- if (jsonObject == null || !jsonObject.containsKey("app") || !jsonObject.containsKey("deviceConfig")
+ JSONObject jsonObject = JSONObject.parseObject(harmonyProfileJsonString);
+ if (jsonObject == null || !jsonObject.containsKey(APP) || !jsonObject.containsKey("deviceConfig")
|| !jsonObject.containsKey("module")) {
LOG.error("Uncompress::parseProfileInfo exception: app, deviceConfig or module is null");
throw new BundleException("Parse profile info failed, app, deviceConfig or module is null");
}
- if (jsonObject.containsKey("app")) {
- JSONObject appJson = jsonObject.getJSONObject("app");
+ if (jsonObject.containsKey(APP)) {
+ JSONObject appJson = jsonObject.getJSONObject(APP);
profileInfo.appInfo = parseAppInfo(appJson);
}
if (jsonObject.containsKey("module")) {
@@ -138,6 +185,9 @@ public class JsonUtil {
}
}
+ if (!parseShellVersionInfoToAppInfo(paclInfoJsonString, profileInfo.appInfo)) {
+ profileInfo.appInfo.setDefaultShellVersion();
+ }
return profileInfo;
}
@@ -157,8 +207,8 @@ public class JsonUtil {
appInfo.bundleName = getJsonString(appJson, "bundleName");
appInfo.vendor = getJsonString(appJson, "vendor");
appInfo.relatedBundleName = getJsonString(appJson, "relatedBundleName");
- if (appJson.containsKey("version")) {
- JSONObject version = appJson.getJSONObject("version");
+ if (appJson.containsKey(VERSION)) {
+ JSONObject version = appJson.getJSONObject(VERSION);
appInfo.versionName = getJsonString(version, "name");
appInfo.versionCode = getJsonString(version, "code");
}
@@ -168,6 +218,7 @@ public class JsonUtil {
appInfo.targetApiVersion = apiVersion.getIntValue("target");
appInfo.releaseType = getJsonString(apiVersion, "releaseType");
}
+ appInfo.setMultiFrameworkBundle(appJson.getBooleanValue(MULTI_FRAMEWORK_BUNDLE));
return appInfo;
}
diff --git a/com/huawei/ohos/README b/com/huawei/ohos/README
index 86d45bf1e4e380a90b2d01aa010c19650652f1ec..3e30fa9a3cdea06c5c0863f0f1ab33924da57cae 100755
--- a/com/huawei/ohos/README
+++ b/com/huawei/ohos/README
@@ -42,9 +42,9 @@ HAP MODE OPTIONS:
--dex-path 1.dex path must end with .dex, if has more than one dex,
use comma(,) to separate.
2.dex path also can be directory path.
- --aex-path 1.aex path must end with .aex, if has more than one aex,
+ --abc-path 1.abc path must end with .abc, if has more than one abc,
use comma(,) to separate.
- 2.aex path also can be directory path.
+ 2.abc path also can be directory path.
--lib-path lib/ path.
--assets-path assets/ path.
--resources-path resources path.
diff --git a/com/huawei/ohos/Uncompress.java b/com/huawei/ohos/Uncompress.java
index 03e21bd2ab54955f598e38a4acdb3d3255d4dd76..80d430c3f7b52219391b2f5b33209aef6e891549 100755
--- a/com/huawei/ohos/Uncompress.java
+++ b/com/huawei/ohos/Uncompress.java
@@ -542,59 +542,43 @@ public class Uncompress {
}
}
- /**
- * uncompress process
- *
- * @param deviceType device type
- * @param srcPath source file path
- * @param fileName uncompress file name
- * @return the uncompress result
- * @throws BundleException FileNotFoundException|IOException.
- */
- private static UncomperssResult uncompress(String deviceType, String srcPath, String fileName)
- throws BundleException {
- if (srcPath.isEmpty() || fileName.isEmpty()) {
- LOG.error("Uncompress::uncompress srcPath, fileName is empty!");
- throw new BundleException("Uncompress failed, srcPath or fileName is empty");
- }
-
- UncomperssResult result = new UncomperssResult();
- InputStream fileInputStream = null;
+ private static byte[] getResourceDataFromHap(ZipFile zipFile) throws BundleException, IOException {
+ int entriesNum = 0;
InputStream indexInputStream = null;
- ZipFile zipFile = null;
- BufferedReader bufferedReader = null;
- byte[] data = null;
try {
- File srcFile = new File(srcPath);
- zipFile = new ZipFile(srcFile);
-
- if (HARMONY_PROFILE.equals(fileName)) {
- int entriesNum = 0;
- for (Enumeration extends ZipEntry> entries = zipFile.entries(); entries.hasMoreElements(); ) {
- entriesNum++;
- if (entriesNum > TOO_MANY_SIZE) {
- LOG.error("Uncompress::uncompress exception: the entry num is too many.");
- throw new BundleException("uncompress failed entry num is too many");
- }
+ for (Enumeration extends ZipEntry> entries = zipFile.entries(); entries.hasMoreElements(); ) {
+ entriesNum++;
+ if (entriesNum > TOO_MANY_SIZE) {
+ LOG.error("Uncompress::uncompress exception: the entry num is too many.");
+ throw new BundleException("uncompress failed entry num is too many");
+ }
- ZipEntry indexEntry = entries.nextElement();
- if (indexEntry == null) {
- continue;
- }
- if (indexEntry != null && !"".equals(indexEntry.getName()) &&
- indexEntry.getName().toLowerCase().endsWith(RESOURCE_INDEX)) {
- indexInputStream = zipFile.getInputStream(indexEntry);
- data = getByte(indexInputStream);
- break;
- }
+ ZipEntry indexEntry = entries.nextElement();
+ if (indexEntry == null) {
+ continue;
+ }
+ if (indexEntry != null && !"".equals(indexEntry.getName()) &&
+ indexEntry.getName().toLowerCase().endsWith(RESOURCE_INDEX)) {
+ indexInputStream = zipFile.getInputStream(indexEntry);
+ return getByte(indexInputStream);
}
}
+ } finally {
+ Utility.closeStream(indexInputStream);
+ }
+ return null;
+ }
- ZipEntry entry = zipFile.getEntry(fileName);
- if (entry == null) {
- LOG.error("Uncompress::uncompress " + fileName + " not found exception");
- throw new BundleException("Uncompress failed");
- }
+ private static String readStringFromFile(String fileName, ZipFile zipFile)
+ throws IOException {
+ ZipEntry entry = zipFile.getEntry(fileName);
+ if (entry == null) {
+ LOG.error("Uncompress::readStringFromFile " + fileName + " not found exception");
+ return "";
+ }
+ InputStream fileInputStream = null;
+ BufferedReader bufferedReader = null;
+ try {
fileInputStream = zipFile.getInputStream(entry);
bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
String line;
@@ -602,50 +586,86 @@ public class Uncompress {
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
- if (PACK_INFO.equals(fileName)) {
- List packInfos = JsonUtil.parseHapList(deviceType, sb.toString());
- result.setPackInfoStr(sb.toString());
- result.setPackInfos(packInfos);
- } else {
- ProfileInfo profileInfo = JsonUtil.parseProfileInfo(sb.toString(), data);
- profileInfo.hapName = srcFile.getName().replace(HAP_SUFFIX, "");
- result.addProfileInfoStr(sb.toString());
- result.addProfileInfo(profileInfo);
- }
- } catch (IOException exception) {
- LOG.error("Uncompress::uncompress io exception: " + exception.getMessage());
- throw new BundleException("Uncompress failed");
+ return sb.toString();
} finally {
Utility.closeStream(bufferedReader);
- Utility.closeStream(indexInputStream);
Utility.closeStream(fileInputStream);
+ }
+ }
+
+ private static HapZipInfo unZipHapFileFromHapFile(String srcPath)
+ throws BundleException, IOException {
+ HapZipInfo hapZipInfo = new HapZipInfo();
+ ZipFile zipFile = null;
+ try {
+ File srcFile = new File(srcPath);
+ zipFile = new ZipFile(srcFile);
+ hapZipInfo.setHarmonyProfileJsonStr(readStringFromFile(HARMONY_PROFILE, zipFile));
+ hapZipInfo.setResDataBytes(getResourceDataFromHap(zipFile));
+ hapZipInfo.setPackInfoJsonStr(readStringFromFile(PACK_INFO, zipFile));
+ hapZipInfo.setHapFileName(getHapNameWithoutSuffix(srcFile.getName()));
+ } finally {
Utility.closeStream(zipFile);
}
- return result;
+ return hapZipInfo;
}
/**
- * uncompress process by InputStream
+ * uncompress from specified file name
*
* @param deviceType device type
- * @param input the InputStream about the package.
+ * @param srcPath source file path
* @param fileName uncompress file name
* @return the uncompress result
* @throws BundleException FileNotFoundException|IOException.
*/
- private static UncomperssResult uncompressByInput(String deviceType, InputStream input, String fileName)
+ private static UncomperssResult uncompress(String deviceType, String srcPath, String fileName)
throws BundleException {
+ if (srcPath.isEmpty() || fileName.isEmpty()) {
+ LOG.error("Uncompress::uncompress srcPath, fileName is empty!");
+ throw new BundleException("Uncompress failed, srcPath or fileName is empty");
+ }
+
UncomperssResult result = new UncomperssResult();
+ try {
+ HapZipInfo hapZipInfo = unZipHapFileFromHapFile(srcPath);
+ if (isPackInfo(fileName)) {
+ uncompressPackInfo(deviceType, hapZipInfo, result);
+ } else {
+ uncompressProfileInfo(hapZipInfo, result);
+ }
+ } catch (IOException exception) {
+ LOG.error("Uncompress::uncompress io exception: " + exception.getMessage());
+ throw new BundleException("Uncompress failed");
+ }
+ return result;
+ }
+
+ private static void uncompressPackInfo(String deviceType, HapZipInfo hapZipInfo, UncomperssResult uncomperssResult)
+ throws BundleException {
+ List packInfos = JsonUtil.parseHapList(deviceType, hapZipInfo.getPackInfoJsonStr());
+ uncomperssResult.setPackInfoStr(hapZipInfo.getPackInfoJsonStr());
+ uncomperssResult.setPackInfos(packInfos);
+ }
+
+ private static void uncompressProfileInfo(HapZipInfo hapZipInfo, UncomperssResult uncomperssResult)
+ throws BundleException {
+ ProfileInfo profileInfo = JsonUtil.parseProfileInfo(hapZipInfo.getHarmonyProfileJsonStr(),
+ hapZipInfo.getResDataBytes(), hapZipInfo.getPackInfoJsonStr());
+ profileInfo.hapName = hapZipInfo.getHapFileName();
+ uncomperssResult.addProfileInfoStr(hapZipInfo.getHarmonyProfileJsonStr());
+ uncomperssResult.addProfileInfo(profileInfo);
+ }
+
+ private static HapZipInfo unZipHapFileFromInputStream(InputStream input) throws BundleException, IOException {
BufferedInputStream bufIn = null;
- InputStream indexInputStream = null;
ZipInputStream zipIn = null;
BufferedReader bufferedReader = null;
+ HapZipInfo hapZipInfo = new HapZipInfo();
try {
ZipEntry entry = null;
bufIn = new BufferedInputStream(input);
zipIn = new ZipInputStream(bufIn);
- String sbStr = "";
- byte[] dataRes = null;
int entriesNum = 0;
while ((entry = zipIn.getNextEntry()) != null) {
entriesNum++;
@@ -655,34 +675,59 @@ public class Uncompress {
}
if (entry.getName().toLowerCase().endsWith(RESOURCE_INDEX)) {
- dataRes = getByte(zipIn);
- } else if (fileName.equals(entry.getName())) {
+ hapZipInfo.setResDataBytes(getByte(zipIn));
+ continue;
+ }
+ if (isPackInfo(entry.getName())) {
bufferedReader = new BufferedReader(new InputStreamReader(zipIn));
- String line;
- StringBuilder sb = new StringBuilder();
- while ((line = bufferedReader.readLine()) != null) {
- sb.append(line);
- }
- sbStr = sb.toString();
+ hapZipInfo.setPackInfoJsonStr(readStringFromInputStream(zipIn, bufferedReader));
+ continue;
+ }
+ if (isHarmonyProfile(entry.getName())) {
+ bufferedReader = new BufferedReader(new InputStreamReader(zipIn));
+ hapZipInfo.setHarmonyProfileJsonStr(readStringFromInputStream(zipIn, bufferedReader));
}
}
+ } finally {
+ Utility.closeStream(bufferedReader);
+ Utility.closeStream(bufIn);
+ Utility.closeStream(zipIn);
+ }
+ return hapZipInfo;
+ }
+
+ private static String readStringFromInputStream(ZipInputStream zipIn, BufferedReader bufferedReader)
+ throws IOException {
+ String line;
+ StringBuilder sb = new StringBuilder();
+ while ((line = bufferedReader.readLine()) != null) {
+ sb.append(line);
+ }
+ return sb.toString();
+ }
- if (PACK_INFO.equals(fileName)) {
- List packInfos = JsonUtil.parseHapList(deviceType, sbStr);
- result.setPackInfoStr(sbStr);
- result.setPackInfos(packInfos);
+ /**
+ * uncompress process by InputStream
+ *
+ * @param deviceType device type
+ * @param input the InputStream about the package.
+ * @param fileName uncompress file name
+ * @return the uncompress result
+ * @throws BundleException FileNotFoundException|IOException.
+ */
+ private static UncomperssResult uncompressByInput(String deviceType, InputStream input, String fileName)
+ throws BundleException {
+ UncomperssResult result = new UncomperssResult();
+ try {
+ HapZipInfo hapZipInfo = unZipHapFileFromInputStream(input);
+ if (isPackInfo(fileName)) {
+ uncompressPackInfo(deviceType, hapZipInfo, result);
} else {
- result.addProfileInfoStr(sbStr);
- result.addProfileInfo(JsonUtil.parseProfileInfo(sbStr, dataRes));
+ uncompressProfileInfo(hapZipInfo, result);
}
} catch (IOException exception) {
LOG.error("Uncompress::uncompressByInput io exception: " + exception.getMessage());
throw new BundleException("Uncompress by input failed");
- } finally {
- Utility.closeStream(bufferedReader);
- Utility.closeStream(indexInputStream);
- Utility.closeStream(bufIn);
- Utility.closeStream(zipIn);
}
return result;
}
@@ -1201,4 +1246,20 @@ public class Uncompress {
}
return result;
}
+
+
+ private static boolean isHarmonyProfile(String fileName) {
+ return HARMONY_PROFILE.equals(fileName);
+ }
+
+ private static boolean isPackInfo(String fileName) {
+ return PACK_INFO.equals(fileName);
+ }
+
+ private static String getHapNameWithoutSuffix(String hapFileName) {
+ if (hapFileName == null || hapFileName.isEmpty()) {
+ return "";
+ }
+ return hapFileName.replace(HAP_SUFFIX, "");
+ }
}
\ No newline at end of file
diff --git a/com/huawei/ohos/Utility.java b/com/huawei/ohos/Utility.java
index 4cad9ccd64a274eec9c3a814fb4e472f5275d579..b1f925898f851e088e97e3e1a266ab108303bf45 100755
--- a/com/huawei/ohos/Utility.java
+++ b/com/huawei/ohos/Utility.java
@@ -45,7 +45,7 @@ public class Utility {
private String soDir = "";
private String abilitySoPath = "";
private String dexPath = "";
- private String aexPath = "";
+ private String abcPath = "";
private String indexPath = "";
private String hapPath = "";
private String appPath = "";
@@ -77,7 +77,7 @@ public class Utility {
private List formattedSoPathList = new ArrayList<>();
private List formattedAbilitySoPathList = new ArrayList<>();
private List formattedDexPathList = new ArrayList<>();
- private List formattedAexPathList = new ArrayList<>();
+ private List formattedAbcPathList = new ArrayList<>();
private List formattedHapPathList = new ArrayList<>();
private List formattedApkPathList = new ArrayList<>();
private List formattedJarPathList = new ArrayList<>();
@@ -154,13 +154,13 @@ public class Utility {
}
}
- public String getAexPath() {
- return aexPath;
+ public String getAbcPath() {
+ return abcPath;
}
- public void setAexPath(String aexPath) {
- if (!aexPath.startsWith(CMD_PREFIX)) {
- this.aexPath = aexPath;
+ public void setAbcPath(String abcPath) {
+ if (!abcPath.startsWith(CMD_PREFIX)) {
+ this.abcPath = abcPath;
}
}
@@ -439,8 +439,8 @@ public class Utility {
return formattedDexPathList;
}
- public List getFormattedAexPathList() {
- return formattedAexPathList;
+ public List getFormattedAbcPathList() {
+ return formattedAbcPathList;
}
public List getFormattedHapPathList() {