diff --git a/adapter/ohos/HapVerify.java b/adapter/ohos/HapVerify.java index 5e5102811de4e9a364fdc5b0b01cc61b3b57fb6d..9b1a03c514c34e88f536bfe7dbbb8f9eaa3e9346 100644 --- a/adapter/ohos/HapVerify.java +++ b/adapter/ohos/HapVerify.java @@ -28,6 +28,8 @@ class HapVerify { private static final String INCLUDE = "include"; private static final String EXCLUDE = "exclude"; private static final Log LOG = new Log(ModuleJsonUtil.class.toString()); + private static final int SERVICE_DEPTH = 2; + private static final int APPLICATION_DEPTH = 5; /** * check hap is verify. @@ -37,7 +39,7 @@ class HapVerify { * @return the result */ public static boolean checkHapIsValid(List hapVerifyInfos) throws BundleException { - if (hapVerifyInfos.isEmpty()) { + if (hapVerifyInfos == null || hapVerifyInfos.isEmpty()) { LOG.error("HapVerify::checkHapIsValid hapVerifyInfos is empty!"); return false; } @@ -66,6 +68,11 @@ class HapVerify { LOG.error("HapVerify::checkHapIsValid failed, entry is not valid!"); return false; } + // check dependency is valid + if (!checkDependencyIsValid(hapVerifyInfos)) { + LOG.error("HapVerify::checkHapIsValid failed, dependency is invalid"); + return false; + } return true; } @@ -281,6 +288,7 @@ class HapVerify { if (checkDistroFilterDisjoint(hapVerifyInfoLeft.distroFilter, hapVerifyInfoRight.distroFilter)) { return true; } + return false; } @@ -327,7 +335,6 @@ class HapVerify { return true; } } - LOG.error("HapVerify::checkDistroFilterDisjoint two distroFilter duplicated!"); return false; } @@ -739,4 +746,129 @@ class HapVerify { exclude.removeAll(include); return Collections.disjoint(exclude, value); } + + /** + * check dependency is valid + * + * @param allHapVerifyInfo is all input hap module + * @return true if dependency is valid + */ + private static boolean checkDependencyIsValid(List allHapVerifyInfo) throws BundleException { + if (allHapVerifyInfo.isEmpty()) { + LOG.error("HapVerify::checkDependencyIsValid failed, input none hap!"); + throw new BundleException("HapVerify::checkDependencyIsValid failed, input none hap!"); + } + boolean installationFree = allHapVerifyInfo.get(0).installationFree; + for (HapVerifyInfo hapVerifyInfo : allHapVerifyInfo) { + if (installationFree != hapVerifyInfo.installationFree) { + LOG.error("HapVerify::checkDependencyIsValid installationFree is different in input hap!"); + return false; + } + } + int depth = installationFree ? SERVICE_DEPTH : APPLICATION_DEPTH; + for (HapVerifyInfo hapVerifyInfo : allHapVerifyInfo) { + List dependencyList = new ArrayList<>(); + dependencyList.add(hapVerifyInfo); + if (!DFSTraverseDependency(hapVerifyInfo, allHapVerifyInfo, dependencyList, depth)) { + return false; + } + dependencyList.remove(dependencyList.size() - 1); + } + return true; + } + + /** + * DFS traverse dependency, and check dependency list ia valid + * + * @param hapVerifyInfo the first node of dependency list + * @param allHapVerifyInfo is all input hap module + * @param dependencyList is the current dependency list + * @param depth is th limit of depth + * @return true if dependency list is valid + */ + private static boolean DFSTraverseDependency(HapVerifyInfo hapVerifyInfo, List allHapVerifyInfo, + List dependencyList, int depth) throws BundleException { + // check dependencyList is valid + if (checkDependencyListCirculate(dependencyList)) { + return false; + } + if (dependencyList.size() > depth + 1) { + LOG.error("HapVerify::DFSTraverseDependency " + dependencyList.get(0).moduleName + " depth exceed!"); + return false; + } + for (String dependency : hapVerifyInfo.dependencies) { + List layerDependencyList = getLayerDependency(dependency, hapVerifyInfo, allHapVerifyInfo); + for(HapVerifyInfo item : layerDependencyList) { + dependencyList.add(item); + if (!DFSTraverseDependency(item, allHapVerifyInfo, dependencyList, depth)) { + return false; + } + dependencyList.remove(dependencyList.size() - 1); + } + } + return true; + } + + /** + * get one layer dependency module by moduleName + * + * @param moduleName is the dependency moduleName of module + * @param hapVerifyInfo the first node of dependency list + * @param allHapVerifyInfo is all input hap module + * @return a layer dependency list + */ + private static List getLayerDependency(String moduleName, HapVerifyInfo hapVerifyInfo, + List allHapVerifyInfo) throws BundleException { + List layerHapVerifyInfoList = new ArrayList<>(); + for (HapVerifyInfo item : allHapVerifyInfo) { + if (item.moduleName.equals(moduleName) && checkModuleJoint(hapVerifyInfo, item)) { + layerHapVerifyInfoList.add(item); + } + } + return layerHapVerifyInfoList; + } + + /** + * check two module is joint + * + * @param infoLeft is one hapVerifyInfo + * @param infoRight is another hapVerifyInfo + * @return true if dependency list is valid + */ + private static boolean checkModuleJoint(HapVerifyInfo infoLeft, HapVerifyInfo infoRight) throws BundleException { + return !checkDuplicatedIsValid(infoLeft, infoRight); + } + + /** + * check dependency list is circulate + * + * @param dependencyList is current dependency list + * @return true if dependency list is circulate + */ + private static boolean checkDependencyListCirculate(List dependencyList) throws BundleException { + for (int i = 0; i < dependencyList.size() - 1; ++i) { + for (int j = i + 1; j < dependencyList.size(); ++j) { + if (isSameHapVerifyInfo(dependencyList.get(i), dependencyList.get(j))) { + LOG.error("HapVerify::checkDependencyListIsValid circular dependency, module is " + + dependencyList.get(0).moduleName); + return true; + } + } + } + return false; + } + + /** + * check two hapVerifyInfo is same.If two module has same moduleName and joint, they are the same hapVerifyInfo + * + * @param infoLeft is one hapVerifyInfo + * @param infoRight is another hapVerifyInfo + * @return true two hapVerifyInfo is same + */ + private static boolean isSameHapVerifyInfo(HapVerifyInfo infoLeft, HapVerifyInfo infoRight) throws BundleException { + if (!infoLeft.moduleName.equals(infoRight.moduleName)) { + return false; + } + return checkModuleJoint(infoLeft, infoRight); + } } diff --git a/adapter/ohos/HapVerifyInfo.java b/adapter/ohos/HapVerifyInfo.java index 2e476d8f3272c1a0e802a2dbe3a2f35d4aec4fc7..eac626eb2a09b0adff0b1f765a8e99c6ea2c531f 100644 --- a/adapter/ohos/HapVerifyInfo.java +++ b/adapter/ohos/HapVerifyInfo.java @@ -64,6 +64,10 @@ class HapVerifyInfo { * Indicates is entry of module. */ public boolean isEntry = false; + /** + * Indicates is installationFree of module. + */ + public boolean installationFree = false; /** * Indicates dependency of module. */ diff --git a/adapter/ohos/ModuleJsonUtil.java b/adapter/ohos/ModuleJsonUtil.java index 5a135fdbc151ca3f0f5aac1b14889a15856ee849..dca9d17b04f2d847171dce78fdadc8c551d1468f 100644 --- a/adapter/ohos/ModuleJsonUtil.java +++ b/adapter/ohos/ModuleJsonUtil.java @@ -68,6 +68,7 @@ class ModuleJsonUtil { private static final String DISTROFILTER = "distroFilter"; private static final String DEPENDENCIES = "dependencies"; private static final String EXTENSIONABILITIES = "extensionAbilities"; + private static final String INSTALLATIONFREE = "installationFree"; private static final Log LOG = new Log(ModuleJsonUtil.class.toString()); /** @@ -786,6 +787,7 @@ class ModuleJsonUtil { hapVerifyInfo.abilityNames.addAll(extensionAbilityNames); hapVerifyInfo.isEntry = parseStageIsEntry(hapVerifyInfo.profileStr); hapVerifyInfo.dependencies = parseDependencies(hapVerifyInfo.profileStr); + hapVerifyInfo.installationFree = parseStageInstallation(hapVerifyInfo.profileStr); } /** @@ -810,6 +812,7 @@ class ModuleJsonUtil { hapVerifyInfo.isEntry = parseFAIsEntry(hapVerifyInfo.profileStr); hapVerifyInfo.packageName = parseFaPackageStr(hapVerifyInfo.profileStr); hapVerifyInfo.dependencies = parseDependencies(hapVerifyInfo.profileStr); + hapVerifyInfo.installationFree = parseFAInstallationFree(hapVerifyInfo.profileStr); } /** @@ -1024,16 +1027,51 @@ class ModuleJsonUtil { * @param jsonString is the json String of module.json or config.json * @return dependencies */ - static List parseDependencies(String jsonString) { + static List parseDependencies(String jsonString) throws BundleException { List dependencies = new ArrayList<>(); JSONObject jsonObj = JSON.parseObject(jsonString); - if (jsonObj.containsKey(MODULE)) { - JSONObject moduleObj = jsonObj.getJSONObject(MODULE); + JSONObject moduleObj = jsonObj.getJSONObject(MODULE); + if (moduleObj == null) { + LOG.error("ModuleJsonUtil::parseStageInstallation json do not contain module!"); + throw new BundleException("ModuleJsonUtil::parseStageInstallation json do not contain module!"); + } + if (moduleObj.containsKey(DEPENDENCIES)) { dependencies = JSONObject.parseArray(getJsonString(moduleObj, DEPENDENCIES), String.class); } return dependencies; } + static boolean parseStageInstallation(String jsonString) throws BundleException { + JSONObject jsonObj = JSON.parseObject(jsonString); + JSONObject moduleObj = jsonObj.getJSONObject(MODULE); + if (moduleObj == null) { + LOG.error("ModuleJsonUtil::parseStageInstallation json do not contain module!"); + throw new BundleException("ModuleJsonUtil::parseStageInstallation json do not contain module!"); + } + if (moduleObj.containsKey(INSTALLATIONFREE)) { + return moduleObj.getBoolean(INSTALLATIONFREE); + } + return false; + } + + static boolean parseFAInstallationFree(String jsonString) throws BundleException { + JSONObject jsonObject = JSON.parseObject(jsonString); + JSONObject moduleObj = jsonObject.getJSONObject(MODULE); + if (moduleObj == null) { + LOG.error("ModuleJsonUtil::parseStageInstallation json do not contain module!"); + throw new BundleException("ModuleJsonUtil::parseStageInstallation json do not contain module!"); + } + JSONObject distroObj = moduleObj.getJSONObject(DISTRO); + if (distroObj == null) { + LOG.error("ModuleJsonUtil::parseStageInstallation json do not contain distro!"); + throw new BundleException("ModuleJsonUtil::parseStageInstallation json do not contain distro!"); + } + if (distroObj.containsKey(INSTALLATIONFREE)) { + return distroObj.getBoolean(INSTALLATIONFREE); + } + return false; + } + /** * get the String from JSONObject by the key. * diff --git a/jar/app_packing_tool.jar b/jar/app_packing_tool.jar index 23592cd48c0ca70c52dcafd51d9d3cf8903e69dd..ab22f13b1130226622658fe4cc0b48cfcf97e23c 100644 Binary files a/jar/app_packing_tool.jar and b/jar/app_packing_tool.jar differ