diff --git a/adapter/ohos/CommandParser.java b/adapter/ohos/CommandParser.java index 8084376ff040b90874d858d836ffdbfa1367e299..8b0463043a15380472c0f61e303b9815ca85bd29 100644 --- a/adapter/ohos/CommandParser.java +++ b/adapter/ohos/CommandParser.java @@ -44,6 +44,8 @@ public class CommandParser { private static final String CMD_HNP_PATH = "--hnp-path"; private static final String CMD_RPCID_PATH = "--rpcid-path"; private static final String CMD_RPCID = "--rpcid"; + private static final String CMD_LIBS = "--libs"; + private static final String CMD_CPU_ABIS = "--cpu-abis"; private static final String CMD_SO_PATH = "--maple-so-path"; private static final String CMD_SO_DIR = "--maple-so-dir"; private static final String CMD_ABILITY_SO_PATH = "--ability-so-path"; @@ -144,6 +146,14 @@ public class CommandParser { entry.getKey().setRpcid(entry.getValue()); return true; }); + commandFuncs.put(CMD_LIBS, entry -> { + entry.getKey().setLibs(entry.getValue()); + return true; + }); + commandFuncs.put(CMD_CPU_ABIS, entry -> { + entry.getKey().setCpuAbis(entry.getValue()); + return true; + }); commandFuncs.put(CMD_SO_PATH, entry -> { entry.getKey().setSoPath(entry.getValue()); return true; diff --git a/adapter/ohos/Uncompress.java b/adapter/ohos/Uncompress.java index b349ddaff7a7aa5639409798c06cbfd2e726b117..ab34991cec5877d34d233acbbca30c4bc33c42a5 100644 --- a/adapter/ohos/Uncompress.java +++ b/adapter/ohos/Uncompress.java @@ -24,6 +24,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; @@ -55,6 +56,8 @@ public class Uncompress { private static final String MODULE_JSON = "module.json"; private static final String RESOURCE_INDEX = "resources.index"; private static final String RPCID_SC = "rpcid.sc"; + private static final String LIBS = "libs"; + private static final String PACKAGEFILE = "packagefile"; private static final String LINUX_FILE_SEPARATOR = "/"; private static final String TEMP_PATH = "temp"; private static final String HAP_SUFFIXI = ".hap"; @@ -73,6 +76,7 @@ public class Uncompress { private static final String PATCH_JSON = "patch.json"; private static final String HAP_PREFIX = "HAP"; private static final String HSP_SUFFIX = ".hsp"; + private static final int Maximum_architecture_type = 128; private static final Log LOG = new Log(Uncompress.class.toString()); @@ -118,7 +122,7 @@ public class Uncompress { uncompressAPPQFFile(utility); break; case Utility.MODE_HSP: - dataTransferAllFiles(utility.getHspPath(), utility.getOutPath()); + unpackageHspMode(utility); break; default: LOG.error("Uncompress::unpackageProcess input wrong type!"); @@ -146,6 +150,10 @@ public class Uncompress { throw new BundleException("Uncompress::unpackageHapMode input wrong unpack mode"); } try { + if (TRUE.equals(utility.getLibs())) { + unpackageLibsMode(utility.getHapPath(), utility.getOutPath(), utility.getFormattedCpuAbiList()); + return; + } if (TRUE.equals(utility.getRpcid())) { getRpcidFromHap(utility.getHapPath(), utility.getOutPath()); return; @@ -164,6 +172,29 @@ public class Uncompress { } } + /** + * unpack hsp. + * + * @param utility common data + */ + static void unpackageHspMode(Utility utility) throws BundleException { + if (!Utility.MODE_HSP.equals(utility.getMode())) { + LOG.error("unpackageHspMode input wrong unpack mode: " + utility.getMode()); + throw new BundleException("Uncompress::unpackageHspMode input wrong unpack mode"); + } + try { + if (TRUE.equals(utility.getLibs())) { + List cpuAbiList = utility.getFormattedCpuAbiList(); + unpackageLibsMode(utility.getHspPath(), utility.getOutPath(), cpuAbiList); + return; + } + dataTransferAllFiles(utility.getHspPath(), utility.getOutPath()); + } catch (BundleException e) { + LOG.error("Uncompress::unpackageHspMode failed"); + throw new BundleException("Uncompress::unpackageHspMode failed"); + } + } + /** * uncompress app. * @@ -1074,8 +1105,8 @@ public class Uncompress { try { String entryName = (baseDir + srcFile.getName()).replace(File.separator, LINUX_FILE_SEPARATOR); ZipEntry zipEntry = new ZipEntry(entryName); - boolean isNeedCompress = isCompression; - if (srcFile.isFile() && srcFile.getName().toLowerCase(Locale.ENGLISH).endsWith(SO_SUFFIX)) { + boolean isNeedCompress = isCompression; + if (srcFile.isFile() && srcFile.getName().toLowerCase(Locale.ENGLISH).endsWith(SO_SUFFIX)) { isNeedCompress = false; } if (isNeedCompress) { @@ -1622,6 +1653,158 @@ public class Uncompress { } } + /** + * unpacking according to the architecture + * + * @param srcFile Indicates the path of hap or hsp. + * @param outPath Indicates the output path of unpacking target path. + * @param cpuAbiList Indicates the designated cpuAbi. + */ + static void unpackageLibsMode(String srcFile, String outPath, List cpuAbiList) throws BundleException { + srcFile = srcFile.replace("\\", LINUX_FILE_SEPARATOR); + outPath = outPath.replace("\\", LINUX_FILE_SEPARATOR); + String tempDir = outPath + LINUX_FILE_SEPARATOR + TEMP_PATH; + try { + List cpuAbiListRes = getLibsFromPackageAndUnpackage(srcFile, tempDir, cpuAbiList); + repackPackage(srcFile, outPath, tempDir, cpuAbiListRes); + } catch (BundleException e) { + LOG.error("Uncompress::unpackageLibsMode failed." ); + throw new BundleException("Uncompress::unpackageLibsMode failed"); + } finally { + File deleteFile = new File(tempDir); + deleteFile(deleteFile); + } + } + + /** + * get libs directory and unpack other files. + * + * @param srcFile Indicates the path of hap or hsp. + * @param tempDirPath Indicates the temporary directory path. + * @param cpuAbiList Indicates the Designated cpuAbi. + */ + static List getLibsFromPackageAndUnpackage(String srcFile, String tempDirPath, List cpuAbiList) + throws BundleException { + try (ZipFile zipFile = new ZipFile(srcFile)) { + final Enumeration entries = zipFile.entries(); + List cpuAbiListRes = new ArrayList<>(); + while (entries.hasMoreElements()) { + final ZipEntry entry = entries.nextElement(); + if (entry.getName().startsWith(LIBS + LINUX_FILE_SEPARATOR )) { + String cpuAbi = entry.getName().substring(LIBS.length()+1).split(LINUX_FILE_SEPARATOR)[0]; + if (!cpuAbiList.isEmpty() && !cpuAbiList.contains(cpuAbi)) { + continue; + } + if (!cpuAbiListRes.contains(cpuAbi)) { + cpuAbiListRes.add(cpuAbi); + } + File tempFile = new File(tempDirPath, entry.getName().substring(LIBS.length()+1)); + createDirectories(tempFile); + try (InputStream inputStream = zipFile.getInputStream(entry); + FileOutputStream outputStream = new FileOutputStream(tempFile)) { + copyStream(inputStream, outputStream); + } + } else { + String tempPath = tempDirPath + LINUX_FILE_SEPARATOR + PACKAGEFILE + LINUX_FILE_SEPARATOR + + entry.getName(); + File destFile = new File(tempPath); + createDirectories(destFile); + dataTransfer(zipFile, entry, destFile); + } + } + if (cpuAbiListRes.size() != cpuAbiList.size() && !cpuAbiList.isEmpty()) { + List notExistAbi = cpuAbiList.stream() + .filter(item -> !cpuAbiListRes.contains(item)) + .collect(Collectors.toList()); + LOG.error("The specified abi does not exist, " + notExistAbi); + throw new BundleException("Uncompress::getLibsFromPackageAndUnpackage failed"); + } + if (cpuAbiListRes.size() > Maximum_architecture_type && cpuAbiList.isEmpty()) + { + LOG.error("Uncompress::getLibsFromPackageAndUnpackage failed: the architecture type exceeds the " + + "limit and must be less than or equal to 128"); + throw new BundleException("Uncompress::getLibsFromPackageAndUnpackage failed"); + } + if (cpuAbiListRes.isEmpty()) { + LOG.error("Uncompress::getLibsFromPackageAndUnpackage failed: No architecture type"); + throw new BundleException("Uncompress::getLibsFromPackageAndUnpackage failed"); + } + return cpuAbiListRes; + } catch (IOException e) { + LOG.error("Uncompress::getLibsFromPackageAndUnpackage IOException " + e.getMessage()); + throw new BundleException("Uncompress::getLibsFromPackageAndUnpackage failed"); + } + } + + private static void createDirectories(File file) { + if (file != null && file.getParentFile() != null && !file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + } + + /** + * copy Stream + * + * @param inputStream input stream + * @param outputStream out stream + * @throws IOException IOException. + */ + private static void copyStream(InputStream inputStream, OutputStream outputStream) throws IOException { + byte[] buffer = new byte[READ_BUFFER_SIZE]; + int bytesRead = 0; + while ((bytesRead = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, bytesRead); + } + } + + /** + * repack Package + * + * @param srcPath source file path + * @param outPath out file path + * @param tempDir temp file name + * @param cpuAbiList cpuAbi list + * @throws BundleException FileNotFoundException|IOException. + */ + private static void repackPackage(String srcPath, String outPath, String tempDir, List cpuAbiList) + throws BundleException { + File srcDir = new File(tempDir + LINUX_FILE_SEPARATOR + PACKAGEFILE); + File[] srcFiles = srcDir.listFiles(); + if (srcFiles == null) { + return; + } + try { + String[] srcPathItem = srcPath.split(LINUX_FILE_SEPARATOR); + if (!(srcPathItem.length > 0)) + { + LOG.error("Uncompress::repackPackage failed"); + throw new BundleException("Uncompress::repackPackage failed"); + } + String hapName = srcPathItem[srcPathItem.length - 1]; + for (String cpuAbi : cpuAbiList) { + String targetZipPath = outPath + LINUX_FILE_SEPARATOR + cpuAbi + LINUX_FILE_SEPARATOR + hapName; + File targetZipFile = new File(targetZipPath); + if (targetZipFile.getParentFile() != null && !targetZipFile.getParentFile().exists()) { + targetZipFile.getParentFile().mkdirs(); + } + ZipOutputStream targetZipOutputStream = new ZipOutputStream(new FileOutputStream(targetZipPath)); + for (File srcFile : srcFiles) { + if (srcFile.isDirectory()) { + compressDirectory(srcFile, "", targetZipOutputStream, false); + } else { + compressFile(srcFile, "", targetZipOutputStream, false); + } + } + File srcFile = new File(tempDir + LINUX_FILE_SEPARATOR + cpuAbi); + compressDirectory(srcFile, LIBS+LINUX_FILE_SEPARATOR, targetZipOutputStream, true); + Utility.closeStream(targetZipOutputStream); + } + } catch (IOException e) { + LOG.error("Uncompress::repackPackage IOException " + e.getMessage()); + throw new BundleException("Uncompress::repackPackage failed"); + } + } + /** * parse resource.index file. * diff --git a/adapter/ohos/UncompressVerify.java b/adapter/ohos/UncompressVerify.java index e46b26d6f6effff7003b76d18a78d47ccc804567..12b5b87ad9338e66f77115a2948e328b6d06f3d6 100644 --- a/adapter/ohos/UncompressVerify.java +++ b/adapter/ohos/UncompressVerify.java @@ -82,7 +82,15 @@ class UncompressVerify { LOG.error("UncompressVerify::isArgsValidInHapMode hap-path must end with.hap!"); return false; } - + + if (!(TRUE.equals(utility.getLibs()) || FALSE.equals(utility.getLibs()))) { + LOG.error("UncompressVerify::isArgsValidInHapMode --libs must be true or false"); + return false; + } + if (TRUE.equals(utility.getLibs())) { + utility.setRpcid(Utility.FALSE_STRING); + return libsCommandVerify(utility); + } if (!(TRUE.equals(utility.getRpcid()) || FALSE.equals(utility.getRpcid()))) { LOG.error("UncompressVerify::isArgsValidInHapMode --rpcid must be true or false"); return false; @@ -101,6 +109,14 @@ class UncompressVerify { LOG.error("UncompressVerify::isArgsValidInHspMode hsp-path must end with.hsp!"); return false; } + + if (!(TRUE.equals(utility.getLibs()) || FALSE.equals(utility.getLibs()))) { + LOG.error("UncompressVerify::isArgsValidInHapMode --libs must be true or false"); + return false; + } + if (TRUE.equals(utility.getLibs())) { + return libsCommandVerify(utility); + } return verifyOutPath(utility, file); } @@ -119,6 +135,35 @@ class UncompressVerify { return true; } + /** + * parse and check args if valid in hap or hsp mode. + * + * @param utility common data + * @return isVerifyValidInLibsMode if verify valid in hap or hsp mode. + */ + private static boolean libsCommandVerify(Utility utility) { + if (utility.getOutPath().isEmpty()) { + LOG.error("--out-path is empty!"); + return false; + } + + File outFile = new File(utility.getOutPath()); + if (("false".equals(utility.getForceRewrite())) && (outFile.exists())) { + LOG.error("UncompressVerify::libsCommandVerify out file already existed!"); + return false; + } + + if (!utility.getCpuAbis().isEmpty()) { + String[] array = utility.getCpuAbis().split(","); + for (String item : array) { + if (!utility.getFormattedCpuAbiList().contains(item)) { + utility.getFormattedCpuAbiList().add(item); + } + } + } + return true; + } + /** * parse and check args if valid in har mode. * diff --git a/adapter/ohos/Utility.java b/adapter/ohos/Utility.java index ed7e67c5f7283feac3c64bf3988df5ffb0ed456c..84d4836032e5ab910f0d10a4c849275dccbb7adc 100644 --- a/adapter/ohos/Utility.java +++ b/adapter/ohos/Utility.java @@ -93,6 +93,8 @@ public class Utility { private String VersionName = ""; private boolean isModuleJson = false; private String rpcid = FALSE_STRING; + private String libs = FALSE_STRING; + private String cpuAbi = ""; private boolean isParse = false; private String appqfPath = ""; private String anPath = ""; @@ -109,6 +111,7 @@ public class Utility { private boolean generateBuildHash = false; private boolean buildHashFinish = false; + private List formattedCpuAbiList = new ArrayList<>(); private List formattedSoPathList = new ArrayList<>(); private List formattedAbilitySoPathList = new ArrayList<>(); private List formattedDexPathList = new ArrayList<>(); @@ -569,6 +572,18 @@ public class Utility { this.rpcid = rpcid; } + public String getLibs() { return libs; } + + public void setLibs(String libs) { + this.libs = libs; + } + + public String getCpuAbis() { return cpuAbi; } + + public void setCpuAbis(String cpuAbi) { + this.cpuAbi = cpuAbi; + } + public String getVersionName() { return VersionName; } @@ -585,6 +600,10 @@ public class Utility { this.VersionCode = VersionCode; } + public List getFormattedCpuAbiList() { + return formattedCpuAbiList; + } + public List getFormattedSoPathList() { return formattedSoPathList; }