1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16package ohos;
17
18import com.alibaba.fastjson.JSON;
19import com.alibaba.fastjson.JSONObject;
20import com.alibaba.fastjson.JSONArray;
21import com.alibaba.fastjson.JSONException;
22
23import java.io.File;
24import java.util.ArrayList;
25import java.util.HashMap;
26import java.util.List;
27import java.util.Map;
28
29class ModuleJsonUtil {
30    private static final String APP = "app";
31    private static final String BUNDLE_TYPE = "bundleType";
32    private static final String ABILITIES = "abilities";
33    private static final String VERSIONCODE = "versionCode";
34    private static final String VERSIONNAME = "versionName";
35    private static final String MIN_COMPATIBLE_VERSION_CODE = "minCompatibleVersionCode";
36    private static final String API_VERSION = "apiVersion";
37    private static final String MIN_API_VERSION = "minAPIVersion";
38    private static final String TARGET_API_VERSION = "targetAPIVersion";
39    private static final String API_RELEASE_TYPE = "apiReleaseType";
40    private static final String DEBUG = "debug";
41    private static final String COMPATIBLE = "compatible";
42    private static final String RELEASE_TYPE = "releaseType";
43    private static final String TARGET = "target";
44    private static final String VERSION = "version";
45    private static final String CODE = "code";
46    private static final String NAME = "name";
47    private static final String SKILLS = "skills";
48    private static final String SKILLS_ENTITIES = "entities";
49    private static final String SKILLS_ACTIONS = "actions";
50    private static final String ACTION_SYSTEM_HOME = "action.system.home";
51    private static final String ENTITY_SYSTEM_HOME = "entity.system.home";
52    private static final String MODULE = "module";
53    private static final String MODULES = "modules";
54    private static final String MODULE_NAME = "moduleName";
55    private static final String MODULE_TYPE = "moduleType";
56    private static final String DISTRO = "distro";
57    private static final String PACKAGE = "package";
58    private static final String PACKAGES = "packages";
59    private static final String SUMMARY = "summary";
60    private static final String BUNDLE_NAME = "bundleName";
61    private static final String ENTRY = "entry";
62    private static final char DOT = '.';
63    private static final String CONFIG_JSON = "config.json";
64    private static final String MODULE_JSON = "module.json";
65    private static final String DEVICE_TYPE = "deviceType";
66    private static final String DEVICE_TYPES = "deviceTypes";
67    private static final String TYPE= "type";
68    private static final String VENDOR = "vendor";
69    private static final String METADATA = "metadata";
70    private static final String RESOURCE = "resource";
71    private static final String PROFILE = "$profile:";
72    private static final String VALUE = "value";
73    private static final String JSON_PERFIX = ".json";
74    private static final String DISTRO_FILTER = "distroFilter";
75    private static final String DISTRIBUTION_FILTER = "distributionFilter";
76    private static final String DEPENDENCIES = "dependencies";
77    private static final String EXTENSION_ABILITIES = "extensionAbilities";
78    private static final String INSTALLATION_FREE = "installationFree";
79    private static final String PATCH_JSON = "patch.json";
80    private static final String PATCH_VERSION_CODE = "patchVersionCode";
81    private static final String PATCH_VERSION_NAME = "patchVersionName";
82    private static final String ORIGINAL_MODULE_HASH = "originalModuleHash";
83    private static final String EMPTY_STRING = "";
84    private static final String COMPRESS_NATIVE_LIBS = "compressNativeLibs";
85    private static final String ASAN_ENABLED = "asanEnabled";
86    private static final String TSAN_ENABLED = "tsanEnabled";
87    private static final String GWP_ASAN_ENABLED = "GWPAsanEnabled";
88    private static final String HW_ASAN_ENABLED = "hwasanEnabled";
89    private static final String UB_SAN_ENABLED = "ubsanEnabled";
90    private static final String ATOMIC_SERVICE = "atomicService";
91    private static final String SPLIT = "split";
92    private static final String MAIN = "main";
93    private static final String PRELOADS = "preloads";
94    private static final String SHARED = "shared";
95    private static final String APP_SERVICE = "appService";
96    private static final String REQUEST_PERMISSIONS = "requestPermissions";
97    private static final String TARGET_MODULE_NAME = "targetModuleName";
98    private static final String TARGET_PRIORITY = "targetPriority";
99    private static final String TARGET_BUNDLE_NAME = "targetBundleName";
100    private static final String DEVICE_CONFIG = "deviceConfig";
101    private static final String DEFAULT = "default";
102    private static final String COMPILE_SDK_VERSION = "compileSdkVersion";
103    private static final String COMPILE_SDK_TYPE = "compileSdkType";
104    private static final String PROXY_DATAS = "proxyDatas";
105    private static final String PROXY_DATA = "proxyData";
106    private static final String PROXY_URI = "uri";
107    private static final String CONTINUE_TYPE = "continueType";
108    private static final String CONTINUE_BUNDLE_NAME = "continueBundleName";
109    private static final String MULTI_APP_MODE = "multiAppMode";
110    private static final String MULTI_APP_MODE_TYPE = "multiAppModeType";
111    private static final String MULTI_APP_MODE_NUMBER = "maxCount";
112    private static final String FORMS = "forms";
113    private static final String DEFAULTDIMENSION = "defaultDimension";
114    private static final String SUPPORTDIMENSIONS = "supportDimensions";
115
116    private static final Log LOG = new Log(ModuleJsonUtil.class.toString());
117
118    /**
119     * get the version from json file for stage module.
120     *
121     * @param jsonString uncompress json object
122     * @return the result
123     * @throws BundleException Throws this exception if the json is not standard.
124     */
125    public static Version parseStageVersion(String jsonString) throws BundleException {
126        Version version = new Version();
127        JSONObject appObj = getAppObj(jsonString);
128        if (appObj.containsKey(VERSIONCODE) && appObj.containsKey(VERSIONNAME)) {
129            version.versionCode = appObj.getIntValue(VERSIONCODE);
130            version.versionName = appObj.getString(VERSIONNAME);
131        } else {
132            String errMsg = "ModuleJsonUtil:parseStageVersion json file do not contain version.";
133            LOG.error(errMsg);
134            throw new BundleException(errMsg);
135        }
136        if (appObj.containsKey(MIN_COMPATIBLE_VERSION_CODE)) {
137            version.minCompatibleVersionCode = appObj.getIntValue(MIN_COMPATIBLE_VERSION_CODE);
138        } else {
139            version.minCompatibleVersionCode = version.versionCode;
140        }
141        return version;
142    }
143
144    /**
145     * get the version from json file for fa module.
146     *
147     * @param jsonString uncompress json object
148     * @return the result
149     * @throws BundleException Throws this exception if the json is not standard.
150     */
151    public static Version parseFaVersion(String jsonString) throws BundleException {
152        JSONObject appObj = getAppObj(jsonString);
153        JSONObject versionObj = appObj.getJSONObject(VERSION);
154        if (versionObj == null) {
155            LOG.error("ModuleJsonUtil:parseFaVersion failed : json file do not version.");
156            throw new BundleException("ModuleJsonUtil:parseFaVersion failed : json file do not version.");
157        }
158        Version version = new Version();
159        if (versionObj.containsKey(CODE) && versionObj.containsKey(NAME)) {
160            version.versionName = versionObj.getString(NAME);
161            version.versionCode = versionObj.getIntValue(CODE);
162        } else {
163            LOG.error("ModuleJsonUtil:parseFaVersion failed : json file do not version name or version code.");
164            throw new BundleException(
165                    "ModuleJsonUtil:parseFaVersion failed : json file do not version name or version code.");
166        }
167        if (versionObj.containsKey(MIN_COMPATIBLE_VERSION_CODE)) {
168            version.minCompatibleVersionCode = versionObj.getIntValue(MIN_COMPATIBLE_VERSION_CODE);
169        } else {
170            version.minCompatibleVersionCode = version.versionCode;
171        }
172        return version;
173    }
174
175    /**
176     * get the bundleType fa module.
177     *
178     * @param jsonString uncompress json object
179     * @return the result
180     * @throws BundleException Throws this exception if the json is not standard.
181     */
182    public static String parseFaBundleType(String jsonString) throws BundleException {
183        boolean installationFree = parseFAInstallationFree(jsonString);
184        if (installationFree) {
185            return ATOMIC_SERVICE;
186        }
187        return APP;
188    }
189
190    /**
191     * get the apiVersion from json file for stage module.
192     *
193     * @param jsonString uncompress json object
194     * @return the result
195     * @throws BundleException Throws this exception if the json is not standard.
196     */
197    public static ModuleApiVersion parseStageModuleApiVersion(String jsonString) throws BundleException {
198        JSONObject appObj = getAppObj(jsonString);
199        ModuleApiVersion moduleApiVersion = new ModuleApiVersion();
200        if (appObj.containsKey(MIN_API_VERSION)) {
201            moduleApiVersion.setCompatibleApiVersion(appObj.getIntValue(MIN_API_VERSION));
202        }
203        if (appObj.containsKey(TARGET_API_VERSION)) {
204            moduleApiVersion.setTargetApiVersion(appObj.getIntValue(TARGET_API_VERSION));
205        }
206        if (appObj.containsKey(API_RELEASE_TYPE)) {
207            moduleApiVersion.setReleaseType(appObj.getString(API_RELEASE_TYPE));
208        }
209        return moduleApiVersion;
210    }
211
212    /**
213     * get the apiVersion from json file for fa module.
214     *
215     * @param jsonString uncompress json object
216     * @return the result
217     * @throws BundleException Throws this exception if the json is not standard.
218     */
219    public static ModuleApiVersion parseFAModuleApiVersion(String jsonString) throws BundleException {
220        JSONObject appObj = getAppObj(jsonString);
221        if (!appObj.containsKey(API_VERSION)) {
222            LOG.error("ModuleJsonUtil::parseFAAPIVersion json file do not contain apiVersion.");
223            throw new BundleException("ModuleJsonUtil::parseFAAPIVersion json file do not contain apiVersion.");
224        }
225        JSONObject apiVersionObj = appObj.getJSONObject(API_VERSION);
226        ModuleApiVersion moduleApiVersion = new ModuleApiVersion();
227        if (apiVersionObj.containsKey(COMPATIBLE)) {
228            moduleApiVersion.setCompatibleApiVersion(apiVersionObj.getIntValue(COMPATIBLE));
229        }
230        if (apiVersionObj.containsKey(RELEASE_TYPE)) {
231            moduleApiVersion.setReleaseType(apiVersionObj.getString(RELEASE_TYPE));
232        }
233        if (apiVersionObj.containsKey(TARGET)) {
234            moduleApiVersion.setTargetApiVersion(apiVersionObj.getIntValue(TARGET));
235        }
236        return moduleApiVersion;
237    }
238
239    /**
240     * get the module name from json file for stage module.
241     *
242     * @param jsonString uncompress json object
243     * @return the result
244     * @throws BundleException Throws this exception if the json is not standard.
245     */
246    public static String parseStageModuleName(String jsonString) throws BundleException {
247        JSONObject moduleObj = getModuleObj(jsonString);
248        String moduleName;
249        if (moduleObj.containsKey(NAME)) {
250            moduleName = moduleObj.getString(NAME);
251        } else {
252            LOG.error("ModuleJsonUtil:parseStageModuleName failed: json file do not contain module name.");
253            throw new BundleException("ModuleJsonUtil:parseStageModuleName failed: json file do not contain module name.");
254        }
255        return moduleName;
256    }
257
258    /**
259     * get the moduleName from json file for stage module.
260     *
261     * @param jsonString uncompress json object
262     * @return the result
263     * @throws BundleException Throws this exception if the json is not standard.
264     */
265    public static String parseFaModuleName(String jsonString) throws BundleException {
266        String moduleName;
267        JSONObject moduleObj = getModuleObj(jsonString);
268        JSONObject distroObj = moduleObj.getJSONObject(DISTRO);
269        if (distroObj == null) {
270            LOG.error("ModuleJsonUtil:parseFaModuleName failed: json file do not contain distro.");
271            throw new BundleException("ModuleJsonUtil:parseFaModuleName failed: json file do not contain distro.");
272        }
273        if (!distroObj.containsKey(MODULE_NAME)) {
274            LOG.error("ModuleJsonUtil:parseFaModuleName failed: json file do not contain moduleName.");
275            throw new BundleException(
276                    "ModuleJsonUtil:parseFaModuleName failed: json file do not contain moduleName.");
277        }
278        moduleName = distroObj.getString(MODULE_NAME);
279        return moduleName;
280    }
281
282    /**
283     * get the moduleName from json file for hqf.
284     *
285     * @param jsonString uncompress json object
286     * @return the result
287     * @throws BundleException Throws this exception if the json is not standard.
288     */
289    public static String parsePatchModuleName(String jsonString) throws BundleException {
290        String moduleName;
291        JSONObject moduleObj = getModuleObj(jsonString);
292        if (!moduleObj.containsKey(NAME)) {
293            LOG.error("ModuleJsonUtil:parsePatchModuleName failed: json file do not contain moduleName.");
294            throw new BundleException(
295                    "ModuleJsonUtil:parsePatchModuleName failed: json file do not contain moduleName.");
296        }
297        moduleName = moduleObj.getString(NAME);
298        return moduleName;
299    }
300
301    /**
302     * get the package from json file for stage module.
303     *
304     * @param jsonString uncompress json object
305     * @return the result
306     * @throws BundleException Throws this exception if the json is not standard.
307     */
308    public static String parseFaPackageStr(String jsonString) throws BundleException {
309        String packageStr = "";
310        JSONObject moduleObj = getModuleObj(jsonString);
311        if (moduleObj.containsKey(PACKAGE)) {
312            packageStr = moduleObj.getString(PACKAGE);
313        } else {
314            LOG.error("ModuleJsonUtil:parseFaPackageStr failed: json file do not contain package.");
315            throw new BundleException("ModuleJsonUtil:parseFaPackageStr failed: json file do not contain package.");
316        }
317        return packageStr;
318    }
319
320    /**
321     * get the bundleName from json file.
322     *
323     * @param jsonString uncompress json object
324     * @return the result
325     * @throws BundleException Throws this exception if the json is not standard.
326     */
327    public static String parseBundleName(String jsonString) throws BundleException {
328        JSONObject appObject = getAppObj(jsonString);
329        String bundleName = "";
330        if (appObject.containsKey(BUNDLE_NAME)) {
331            bundleName = appObject.getString(BUNDLE_NAME);
332        } else {
333            LOG.error("ModuleJsonUtil::parseStageBundleName json object do not contain bundleNames.");
334            throw new BundleException("ModuleJsonUtil::parseStageBundleName json object do not contain bundleNames.");
335        }
336        return bundleName;
337    }
338
339    /**
340     * get the vendor from json file.
341     *
342     * @param jsonString uncompress json object
343     * @return the result
344     * @throws BundleException Throws this exception if the json is not standard.
345     */
346    public static String parseVendor(String jsonString) throws BundleException {
347        JSONObject appObject = getAppObj(jsonString);
348        String vendor = "";
349        if (appObject.containsKey(VENDOR)) {
350            vendor = appObject.getString(VENDOR);
351        }
352        return vendor;
353    }
354
355    /**
356     * merge two pack.info file into one pack.info file.
357     *
358     * @param finalPackInfo is the final packInfo
359     * @param srcPackInfo is the packInfo to be merged
360     * @return the result
361     * @throws BundleException Throws this exception if the json is not standard.
362     */
363    public static String mergeTwoPackInfo(String finalPackInfo, String srcPackInfo) throws BundleException {
364        String desPackInfo = "";
365        JSONObject finalPackObj;
366        try {
367            finalPackObj = JSON.parseObject(finalPackInfo);
368            JSONObject srcPackObj = JSON.parseObject(srcPackInfo);
369            if (!verifyPackInfo(finalPackObj, srcPackObj)) {
370                LOG.error("ModuleJsonUtil:mergeTwoPackInfo verify pack.info failed.");
371                throw new BundleException("ModuleJsonUtil:mergeTwoPackInfo verify pack.info failed.");
372            }
373            desPackInfo = mergePackInfoObj(finalPackObj, srcPackObj);
374        } catch (BundleException | JSONException e) {
375            LOG.error("ModuleJsonUtil:mergeTwoPackInfo merge pack.info failed: " + e.getMessage());
376            throw new BundleException("ModuleJsonUtil:mergeTwoPackInfo merge pack.info failed.");
377        }
378        return desPackInfo;
379    }
380
381    /**
382     * verify pack.info file.
383     *
384     * @param finalPackObj is the final pack.info object
385     * @param srcPackObj is the src pack.info object
386     * @return the result
387     */
388    public static boolean verifyPackInfo(JSONObject finalPackObj, JSONObject srcPackObj) throws BundleException {
389        if (finalPackObj == null || srcPackObj == null) {
390            LOG.error("ModuleJsonUtil:verifyPackInfo fail to read pack.info.");
391            return false;
392        }
393        JSONObject finalSummaryObj = finalPackObj.getJSONObject(SUMMARY);
394        JSONObject srcSummaryObj = srcPackObj.getJSONObject(SUMMARY);
395        if (finalSummaryObj == null || srcSummaryObj == null) {
396            LOG.error("ModuleJsonUtil:verifyPackInfo pack.info do not contain summary.");
397            return false;
398        }
399        // check app info
400        JSONObject finalAppObj = finalSummaryObj.getJSONObject(APP);
401        JSONObject srcAppObj = srcSummaryObj.getJSONObject(APP);
402        if (finalAppObj == null || srcAppObj == null) {
403            LOG.error("ModuleJsonUtil:verifyPackInfo pack.info do not contain app.");
404            return false;
405        }
406        if (!verifyAppInPackInfo(finalAppObj, srcAppObj)) {
407            LOG.error("ModuleJsonUtil:verifyPackInfo verify app failed.");
408            return false;
409        }
410
411        return true;
412    }
413
414    /**
415     * verify app in pack.info file.
416     *
417     * @param finalAppObj is the final pack.info app object
418     * @param srcAppObj is the src pack.info app object
419     * @return the result
420     */
421    public static boolean verifyAppInPackInfo(JSONObject finalAppObj, JSONObject srcAppObj) {
422        if (finalAppObj == null || srcAppObj == null) {
423            LOG.error("ModuleJsonUtil:verifyAppInPackInfo input null json object.");
424            return false;
425        }
426        // check bundleName
427        String finalBundleName = finalAppObj.getString(BUNDLE_NAME);
428        String srcBundleName = srcAppObj.getString(BUNDLE_NAME);
429        if (!finalBundleName.equals(srcBundleName)) {
430            LOG.error("ModuleJsonUtil:verifyAppInPackInfo bundleName is different.");
431            return false;
432        }
433        // check bundleType
434        if (!checkBundleTypeInPackInfo(finalAppObj, srcAppObj)) {
435            LOG.error("ModuleJsonUtil:verifyAppInPackInfo bundleType is different.");
436            return false;
437        }
438        // check version
439        JSONObject finalVersionObj = finalAppObj.getJSONObject(VERSION);
440        JSONObject srcVersionObj = srcAppObj.getJSONObject(VERSION);
441        if (finalVersionObj == null || srcVersionObj == null) {
442            LOG.error("ModuleJsonUtil:verifyAppInPackInfo version object is empty.");
443            return false;
444        }
445        int finalVersionCode = finalVersionObj.getIntValue(CODE);
446        int srcVersionCode = srcVersionObj.getIntValue(CODE);
447        if (finalVersionCode != srcVersionCode) {
448            LOG.error("ModuleJsonUtil:verifyAppInPackInfo versionCode is different.");
449            return false;
450        }
451        return true;
452    }
453
454    /**
455     * verify bundleType in pack.info file.
456     *
457     * @param finalAppObj is the final pack.info app objects
458     * @param srcAppObj is the src pack.info app objects
459     * @return the result
460     */
461    public static boolean checkBundleTypeInPackInfo(JSONObject finalAppObj, JSONObject srcAppObj) {
462        if (finalAppObj.isEmpty() || srcAppObj.isEmpty()) {
463            LOG.error("ModuleJsonUtil:checkBundleTypeInPackInfo pack.info has empty module.");
464            return false;
465        }
466        String finalBundleType = "app";
467        String srcBundleType = "app";
468        if (finalAppObj.containsKey(BUNDLE_TYPE)) {
469            finalBundleType = getJsonString(finalAppObj, BUNDLE_TYPE);
470        }
471        if (srcAppObj.containsKey(BUNDLE_TYPE)) {
472            srcBundleType = getJsonString(srcAppObj, BUNDLE_TYPE);
473        }
474        if (!finalBundleType.equals(srcBundleType)) {
475            LOG.error("bundleType in pack.info is not same.");
476            return false;
477        }
478        return true;
479    }
480
481    /**
482     * verify module in pack.info file.
483     *
484     * @param finalModuleObs is the final pack.info module objects
485     * @param srcModuleObs is the src pack.info module objects
486     * @return the result
487     */
488    public static boolean verifyModuleInPackInfo(JSONArray finalModuleObs, JSONArray srcModuleObs)
489            throws BundleException {
490        if (finalModuleObs.isEmpty() || srcModuleObs.isEmpty()) {
491            LOG.error("ModuleJsonUtil:verifyModuleInPackInfo pack.info has empty module.");
492            throw new BundleException("ModuleJsonUtil:verifyModuleInPackInfo pack.info has empty module.");
493        }
494        List<String> moduleNames = new ArrayList<>();
495        for (int i = 0; i < finalModuleObs.size(); ++i) {
496            JSONObject finalModuleObj = finalModuleObs.getJSONObject(i);
497            String moduleName = parseDistroModuleName(finalModuleObj);
498            if (moduleNames.contains(moduleName)) {
499                LOG.error("ModuleJsonUtil:verifyModuleInPackInfo duplicated moduleName.");
500                return false;
501            } else {
502                moduleNames.add(moduleName);
503            }
504        }
505        for (int i = 0; i < srcModuleObs.size(); ++i) {
506            JSONObject srcModuleObj = srcModuleObs.getJSONObject(i);
507            String moduleName = parseDistroModuleName(srcModuleObj);
508            if (moduleNames.contains(moduleName)) {
509                LOG.error("ModuleJsonUtil:verifyModuleInPackInfo duplicated moduleName.");
510                return false;
511            } else {
512                moduleNames.add(moduleName);
513            }
514        }
515        return true;
516    }
517
518
519
520    /**
521     * parse forms name in pack.info file.
522     *
523     * @param jsonString the pack.info json string
524     * @param formNameList the forms name in pack.info
525     * @param fullFormNameList the forms name and moduleName merged result in pack.info
526     */
527    public static void parsePackInfoFormsName(String jsonString, List<String> formNameList, List<String> fullFormNameList)
528            throws BundleException {
529        JSONObject jsonObject = JSONObject.parseObject(jsonString);
530        if (jsonObject == null || !jsonObject.containsKey(SUMMARY)) {
531            LOG.error("ModuleJsonUtil::parsePackInfoFormsName error: summary is null.");
532            throw new BundleException("Parse pack info forms name failed, summary is null.");
533        }
534
535        JSONObject summaryJson = jsonObject.getJSONObject(SUMMARY);
536        if (summaryJson == null || !summaryJson.containsKey("modules")) {
537            LOG.error("ModuleJsonUtil::parsePackInfoFormsName error: summary.modules is null.");
538            return;
539        }
540
541        JSONArray moduleJsonList = summaryJson.getJSONArray("modules");
542        for (int i = 0; i < moduleJsonList.size(); i++) {
543            JSONObject moduleJson = moduleJsonList.getJSONObject(i);
544            if (moduleJson == null || !moduleJson.containsKey(DISTRO)) {
545                LOG.error("ModuleJsonUtil::parsePackInfoFormsName error: summary.modules.distro is null.");
546                continue;
547            }
548
549            JSONObject distroObj = moduleJson.getJSONObject(DISTRO);
550            if (distroObj == null || !distroObj.containsKey(MODULE_NAME)) {
551                LOG.error("ModuleJsonUtil::parsePackInfoFormsName error: summary.modules.distro.moduleName is null.");
552                continue;
553            }
554
555            String moduleName = distroObj.getString(MODULE_NAME);
556            parsePackInfoExtensionAbility(moduleName, moduleJson, formNameList, fullFormNameList);
557        }
558    }
559
560    /**
561     * verify package name in pack.info file.
562     *
563     * @param finalPackageObs is the final pack.info objects
564     * @param srcPackageObs is the src pack.info objects
565     * @return the result
566     */
567    public static boolean verifyPackageName(JSONArray finalPackageObs, JSONArray srcPackageObs) {
568        if (finalPackageObs == null || finalPackageObs.isEmpty() || srcPackageObs == null || srcPackageObs.isEmpty()) {
569            LOG.error("ModuleJsonUtil:verifyPackageName pack.info has empty packages.");
570            return false;
571        }
572        List<String> packageNames = new ArrayList<>();
573        for (int i = 0; i < finalPackageObs.size(); ++i) {
574            JSONObject packageObj = finalPackageObs.getJSONObject(i);
575            String packageName = packageObj.getString(NAME);
576            if (packageNames.contains(packageName)) {
577                LOG.error("ModuleJsonUtil:verifyPackageName duplicated package name.");
578                return false;
579            } else {
580                packageNames.add(packageName);
581            }
582        }
583        for (int i = 0; i < srcPackageObs.size(); ++i) {
584            JSONObject packageObj = srcPackageObs.getJSONObject(i);
585            String packageName = packageObj.getString(NAME);
586            if (packageNames.contains(packageName)) {
587                LOG.error("ModuleJsonUtil:verifyPackageName duplicated package name.");
588                return false;
589            } else {
590                packageNames.add(packageName);
591            }
592        }
593        return true;
594    }
595
596    /**
597     * parse moduleName in pack.info file.
598     *
599     * @param moduleObj is the final pack.info objects
600     * @return the result
601     */
602    public static String parseDistroModuleName(JSONObject moduleObj) throws BundleException {
603        String moduleName = "";
604        try {
605            if (moduleObj == null) {
606                LOG.error("ModuleJsonUtil:parseFaModuleName failed: json file do not contain module.");
607                throw new BundleException("ModuleJsonUtil:parseFaModuleName failed: json file do not contain module.");
608            }
609            JSONObject distroObj = moduleObj.getJSONObject(DISTRO);
610            if (distroObj == null) {
611                LOG.error("ModuleJsonUtil:parseFaModuleName failed: json file do not contain distro.");
612                throw new BundleException("ModuleJsonUtil:parseFaModuleName failed: json file do not contain distro.");
613            }
614            if (!distroObj.containsKey(MODULE_NAME)) {
615                LOG.error("ModuleJsonUtil:parseFaModuleName failed: json file do not contain moduleName.");
616                throw new BundleException("ModuleJsonUtil:parseFaModuleName failed:" +
617                        "json file do not contain moduleName.");
618            }
619            moduleName = distroObj.getString(MODULE_NAME);
620        } catch (BundleException e) {
621            LOG.error("ModuleJsonUtil:parseFaModuleName failed.");
622            throw new BundleException("ModuleJsonUtil:parseFaModuleName failed.");
623        }
624        return moduleName;
625    }
626
627    /**
628     * merge pack.info file.
629     *
630     * @param finalPackinfoObj is the final pack.info objects
631     * @param srcPackinfoObj is the final pack.info objects
632     * @return the result
633     */
634    public static String mergePackInfoObj(JSONObject finalPackinfoObj, JSONObject srcPackinfoObj) throws BundleException {
635        if (finalPackinfoObj == null || srcPackinfoObj == null) {
636            String errMsg = "ModuleJsonUtil:mergePackInfoObj input an invalid json object.";
637            LOG.error(errMsg);
638            throw new BundleException(errMsg);
639        }
640        JSONObject finalSummaryObj = finalPackinfoObj.getJSONObject(SUMMARY);
641        JSONObject srcSummaryObj = srcPackinfoObj.getJSONObject(SUMMARY);
642        if (finalSummaryObj == null || srcSummaryObj == null) {
643            String errMsg = "ModuleJsonUtil:mergePackInfoObj input json file has empty summary.";
644            LOG.error(errMsg);
645            throw new BundleException(errMsg);
646        }
647        // merge modules
648        JSONArray finalModuleObs = finalSummaryObj.getJSONArray(MODULES);
649        JSONArray srcModuleObs = srcSummaryObj.getJSONArray(MODULES);
650        if (finalModuleObs == null || srcModuleObs == null) {
651            String errMsg = "ModuleJsonUtil:mergePackInfoObj input json file has empty module.";
652            LOG.error(errMsg);
653            throw new BundleException(errMsg);
654        }
655        finalModuleObs.addAll(srcModuleObs);
656        // merge packages
657        JSONArray finalPackageObs = finalPackinfoObj.getJSONArray(PACKAGES);
658        JSONArray srcPackageObs = srcPackinfoObj.getJSONArray(PACKAGES);
659        if (finalPackageObs == null || srcPackageObs == null) {
660            String errMsg = "ModuleJsonUtil:mergePackInfoObj input json file has empty packages.";
661            LOG.error(errMsg);
662            throw new BundleException(errMsg);
663        }
664        finalPackageObs.addAll(srcPackageObs);
665        return finalPackinfoObj.toString();
666    }
667
668    /**
669     * merge two pack.info file into one pack.info file by packagePair.
670     *
671     * @param finalPackInfo is the final packInfo
672     * @param srcPackInfo is the packInfo to be merged
673     * @param packagePair is the selected packageName-moduleName pair map
674     * @return the result
675     * @throws BundleException Throws this exception if the json is not standard.
676     */
677    public static String mergeTwoPackInfoByPackagePair(String finalPackInfo, String srcPackInfo,
678                                                       HashMap<String, String> packagePair) throws BundleException {
679        JSONObject finalPackObj;
680        JSONObject srcPackObj;
681        try {
682            finalPackObj = JSON.parseObject(finalPackInfo);
683            srcPackObj = JSON.parseObject(srcPackInfo);
684        } catch (JSONException exception) {
685            String errMsg = "parse JSONObject failed: " + exception.getMessage();
686            LOG.error(errMsg);
687            throw new BundleException(errMsg);
688        }
689        // verify app in pack.info
690        JSONObject finalSummaryObj = finalPackObj.getJSONObject(SUMMARY);
691        JSONObject finalAppObj = finalSummaryObj.getJSONObject(APP);
692        JSONObject srcSummaryObj = srcPackObj.getJSONObject(SUMMARY);
693        JSONObject srcAppObj = srcSummaryObj.getJSONObject(APP);
694        if (!verifyAppInPackInfo(finalAppObj, srcAppObj)) {
695            String errMsg = "verify pack.info failed, different version, bundleType or bundleName.";
696            LOG.error(errMsg);
697            throw new BundleException(errMsg);
698        }
699        for (HashMap.Entry<String, String> entry : packagePair.entrySet()) {
700            String packageName = entry.getKey().substring(0, entry.getKey().lastIndexOf(DOT));
701            mergeTwoPackInfoObjByPackagePair(finalPackObj, srcPackObj, packageName, entry.getValue());
702        }
703        return finalPackObj.toString();
704    }
705
706    /**
707     * merge two pack.info file into one pack.info file by packagePair.
708     *
709     * @param finalPackObj is the final packInfo
710     * @param srcPackObj is the packInfo to be merged
711     * @param packageName is the selected packageName
712     * @param moduleName is the selected moduleName
713     * @throws BundleException Throws this exception if the json is not standard.
714     */
715    public static void mergeTwoPackInfoObjByPackagePair(JSONObject finalPackObj, JSONObject srcPackObj,
716                                                        String packageName, String moduleName) throws BundleException {
717        if (finalPackObj == null || srcPackObj == null) {
718            String errMsg = "ModuleJsonUtil:mergeTwoPackInfoObjByPackagePair failed: pack.info is not json object.";
719            LOG.error(errMsg);
720            throw new BundleException(errMsg);
721        }
722        // merge module
723        JSONObject finalSummaryObj = finalPackObj.getJSONObject(SUMMARY);
724        JSONObject srcSummaryObj = srcPackObj.getJSONObject(SUMMARY);
725        if (finalSummaryObj == null || srcSummaryObj == null) {
726            String errMsg = "ModuleJsonUtil:mergeTwoPackInfoObjByPackagePair failed: pack.info do not contain summary.";
727            LOG.error(errMsg);
728            throw new BundleException(errMsg);
729        }
730        JSONArray finalModules = finalSummaryObj.getJSONArray(MODULES);
731        JSONArray srcModules = srcSummaryObj.getJSONArray(MODULES);
732        if (finalModules == null || srcModules == null) {
733            LOG.error("ModuleJsonUtil:mergeTwoPackInfoObjByPackagePair input json file has empty module.");
734            throw new
735                BundleException("ModuleJsonUtil:mergeTwoPackInfoObjByPackagePair input json file has empty module.");
736        }
737        boolean findModule = false;
738        for (int index = 0; index < srcModules.size(); ++index) {
739            JSONObject moduleObj = srcModules.getJSONObject(index);
740            JSONObject distroObj = moduleObj.getJSONObject(DISTRO);
741            if (distroObj.getString(MODULE_NAME).equals(moduleName)) {
742                finalModules.add(moduleObj);
743                findModule = true;
744                break;
745            }
746        }
747        if (!findModule) {
748            String errMsg = "ModuleJsonUtil:mergeTwoPackInfoObjByPackagePair" +
749                    " input json do not contain " + moduleName + ".";
750            LOG.error(errMsg);
751            throw new BundleException(errMsg);
752        }
753        // merge package
754        JSONArray finalPackages = finalPackObj.getJSONArray(PACKAGES);
755        JSONArray srcPackages = srcPackObj.getJSONArray(PACKAGES);
756        if (finalPackages == null || srcPackages == null) {
757            String errMsg =
758                    "ModuleJsonUtil:mergeTwoPackInfoObjByPackagePair failed: pack.info do not contain packages.";
759            LOG.error(errMsg);
760            throw new BundleException(errMsg);
761        }
762        boolean findPackage = false;
763        for (int index = 0; index < srcPackages.size(); ++index) {
764            JSONObject srcPackageObj = srcPackages.getJSONObject(index);
765            if (srcPackageObj.getString(NAME).equals(packageName)) {
766                finalPackages.add(srcPackageObj);
767                findPackage = true;
768                break;
769            }
770        }
771        if (!findPackage) {
772            String errMsg = "ModuleJsonUtil:mergeTwoPackInfoObjByPackagePair input json do not contain "
773                    + packageName + ".";
774            LOG.error(errMsg);
775            throw new BundleException(errMsg);
776        }
777    }
778
779    /**
780     * parse FA hap is entry hap, if it is, return device type.
781     *
782     * @param hapPath is the path of hap.
783     *
784     * @throws BundleException FileNotFoundException|IOException.
785     */
786    public static List<String> parseFaEntry(String hapPath) throws BundleException {
787        String configJson = FileUtils.getJsonInZips(new File(hapPath), CONFIG_JSON);
788        JSONObject faObj;
789        try {
790            faObj = JSONObject.parseObject(configJson);
791        } catch (JSONException exception) {
792            String errMsg = "parse JSONobject failed.";
793            LOG.error(errMsg);
794            throw new BundleException(errMsg);
795        }
796        JSONObject moduleObj = faObj.getJSONObject(MODULE);
797        if (moduleObj == null) {
798            String errMSg = "ModuleJsonUtil::isFaEntry error, json do not contain module.";
799            LOG.error(errMSg);
800            throw new BundleException(errMSg);
801        }
802        List<String> deviceTypes = new ArrayList<>();
803        JSONObject distroObj = moduleObj.getJSONObject(DISTRO);
804        if (distroObj == null) {
805            String errMSg = "ModuleJsonUtil::isFaEntry error, json do not contain distro.";
806            LOG.error(errMSg);
807            throw new BundleException(errMSg);
808        }
809        String moduleType = distroObj.getString(MODULE_TYPE);
810        if (ENTRY.equals(moduleType)) {
811            deviceTypes = getDeviceTypeFromFAModule(moduleObj);
812        }
813        return deviceTypes;
814    }
815
816    /**
817     * parse stage hap is entry hap, if it is, record device type.
818     *
819     * @param hapPath is the path of hap.
820     * @throws BundleException FileNotFoundException|IOException.
821     */
822    public static List<String> parseStageEntry(String hapPath) throws BundleException {
823        String moduleJson = FileUtils.getJsonInZips(new File(hapPath), MODULE_JSON);
824        JSONObject stageObj;
825        try {
826            stageObj = JSONObject.parseObject(moduleJson);
827        } catch (JSONException exception) {
828            String errMsg = "parse JSONobject failed.";
829            LOG.error(errMsg);
830            throw new BundleException(errMsg);
831        }
832        JSONObject moduleObj = stageObj.getJSONObject(MODULE);
833        if (moduleObj == null) {
834            String errMSg = "ModuleJsonUtil::isFaEntry error, json do not contain module.";
835            LOG.error(errMSg);
836            throw new BundleException(errMSg);
837        }
838        List<String> deviceTypes = new ArrayList<>();
839        String type = moduleObj.getString(TYPE);
840        if (type != null && type.equals(ENTRY)) {
841            deviceTypes = getDeviceTypesFromStageModule(moduleObj);
842        }
843
844        return deviceTypes;
845    }
846
847    /**
848     * get deviceType from fa module.
849     *
850     * @param moduleObj is the object of module.
851     * @return true is for entry hap  and false is other kind of hap
852     */
853    public static List<String> getDeviceTypeFromFAModule(JSONObject moduleObj) {
854        List<String> deviceTypes = new ArrayList<>();
855        if (moduleObj == null) {
856            return deviceTypes;
857        }
858        deviceTypes = JSONObject.parseArray(getJsonString(moduleObj, DEVICE_TYPE), String.class);
859        return deviceTypes;
860    }
861
862    /**
863     * get deviceType from stage module.
864     *
865     * @param moduleObj is the object of module.
866     * @return true is for entry hap  and false is other kind of hap
867     */
868    public static List<String> getDeviceTypesFromStageModule(JSONObject moduleObj) {
869        List<String> deviceTypes = new ArrayList<>();
870        if (moduleObj == null) {
871            return deviceTypes;
872        }
873        deviceTypes = JSONObject.parseArray(getJsonString(moduleObj, DEVICE_TYPES), String.class);
874        return deviceTypes;
875    }
876
877    /**
878     * parse stage hapVerifyInfo.
879     *
880     * @param hapVerifyInfo is the parse result
881     * @throws BundleException Throws this exception if the json is not standard.
882     */
883    public static void parseStageHapVerifyInfo(HapVerifyInfo hapVerifyInfo) throws BundleException {
884        if (hapVerifyInfo.getProfileStr().isEmpty()) {
885            throw new BundleException("ModuleJsonUtil::parseStageHapVerifyInfo failed, module.json is empty.");
886        }
887        String bundleName = parseBundleName(hapVerifyInfo.getProfileStr());
888        hapVerifyInfo.setBundleName(bundleName);
889        hapVerifyInfo.setVendor(parseVendor(hapVerifyInfo.getProfileStr()));
890        hapVerifyInfo.setVersion(parseStageVersion(hapVerifyInfo.getProfileStr()));
891        hapVerifyInfo.setApiVersion(parseStageModuleApiVersion(hapVerifyInfo.getProfileStr()));
892        hapVerifyInfo.setModuleName(parseStageModuleName(hapVerifyInfo.getProfileStr()));
893        List<ModuleMetadataInfo> moduleMetadataInfos =
894                parseModuleAllMetadata(hapVerifyInfo.getProfileStr(), hapVerifyInfo.getResourceMap());
895        hapVerifyInfo.setDistroFilter(parseStageDistroFilter(moduleMetadataInfos));
896        hapVerifyInfo.setDeviceType(parseDeviceType(hapVerifyInfo.getProfileStr()));
897        hapVerifyInfo.setAbilityNames(parseAbilityNames(hapVerifyInfo.getProfileStr()));
898        List<String> extensionAbilityNames = parseExtensionAbilityName(hapVerifyInfo.getProfileStr());
899        hapVerifyInfo.addAbilityNames(extensionAbilityNames);
900        hapVerifyInfo.setModuleType(parseModuleType(hapVerifyInfo.getProfileStr()));
901        hapVerifyInfo.setDependencyItemList(parseDependencies(hapVerifyInfo.getProfileStr(), bundleName));
902        hapVerifyInfo.setInstallationFree(parseStageInstallation(hapVerifyInfo.getProfileStr()));
903        hapVerifyInfo.setBundleType(parseStageBundleType(hapVerifyInfo.getProfileStr()));
904        hapVerifyInfo.setPreloadItems(parseAtomicServicePreloads(hapVerifyInfo.getProfileStr()));
905        hapVerifyInfo.setTargetBundleName(parseTargetBundleName(hapVerifyInfo.getProfileStr()));
906        hapVerifyInfo.setTargetPriority(parseTargetPriority(hapVerifyInfo.getProfileStr()));
907        hapVerifyInfo.setTargetModuleName(parseTargetModuleName(hapVerifyInfo.getProfileStr()));
908        hapVerifyInfo.setTargetModulePriority(parseTargetModulePriority(hapVerifyInfo.getProfileStr()));
909        hapVerifyInfo.setDebug(getDebug(hapVerifyInfo.getProfileStr()));
910        hapVerifyInfo.setCompileSdkType(getCompileSdkType(hapVerifyInfo.getProfileStr()));
911        hapVerifyInfo.setCompileSdkVersion(getCompileSdkVersion(hapVerifyInfo.getProfileStr()));
912        hapVerifyInfo.setProxyDataUris(parseProxyDataUri(hapVerifyInfo.getProfileStr()));
913        hapVerifyInfo.setContinueTypeMap(parseAbilityContinueTypeMap(hapVerifyInfo.getProfileStr()));
914        hapVerifyInfo.setMultiAppMode(parseMultiAppMode(hapVerifyInfo.getProfileStr()));
915    }
916
917    /**
918     * parse FA hapVerifyInfo.
919     *
920     * @param hapVerifyInfo is the parse result
921     * @throws BundleException Throws this exception if the json is not standard.
922     */
923    public static void parseFAHapVerifyInfo(HapVerifyInfo hapVerifyInfo) throws BundleException {
924        if (hapVerifyInfo.getProfileStr().isEmpty()) {
925            LOG.error("ModuleJsonUtil::parseFAHapVerifyInfo failed, config.json is empty.");
926            throw new BundleException("ModuleJsonUtil::parseFAHapVerifyInfo failed, config.json is empty.");
927        }
928        String bundleName = parseBundleName(hapVerifyInfo.getProfileStr());
929        hapVerifyInfo.setBundleName(bundleName);
930        hapVerifyInfo.setBundleType(parseFaBundleType(hapVerifyInfo.getProfileStr()));
931        hapVerifyInfo.setVendor(parseVendor(hapVerifyInfo.getProfileStr()));
932        hapVerifyInfo.setVersion(parseFaVersion(hapVerifyInfo.getProfileStr()));
933        hapVerifyInfo.setApiVersion(parseFAModuleApiVersion(hapVerifyInfo.getProfileStr()));
934        hapVerifyInfo.setModuleName(parseFaModuleName(hapVerifyInfo.getProfileStr()));
935        hapVerifyInfo.setDistroFilter(parseFADistroFilter(hapVerifyInfo.getProfileStr()));
936        hapVerifyInfo.setDeviceType(parseDeviceType(hapVerifyInfo.getProfileStr()));
937        hapVerifyInfo.setAbilityNames(parseAbilityNames(hapVerifyInfo.getProfileStr()));
938        hapVerifyInfo.setModuleType(parseFAIsEntry(hapVerifyInfo.getProfileStr()));
939        hapVerifyInfo.setPackageName(parseFaPackageStr(hapVerifyInfo.getProfileStr()));
940        hapVerifyInfo.setDependencyItemList(parseDependencies(hapVerifyInfo.getProfileStr(), bundleName));
941        hapVerifyInfo.setInstallationFree(parseFAInstallationFree(hapVerifyInfo.getProfileStr()));
942        hapVerifyInfo.setDebug(getFADebug(hapVerifyInfo.getProfileStr()));
943        hapVerifyInfo.setCompileSdkType(getFACompileSdkType(hapVerifyInfo.getProfileStr()));
944        hapVerifyInfo.setCompileSdkVersion(getFACompileSdkVersion(hapVerifyInfo.getProfileStr()));
945    }
946
947    private static MultiAppMode parseMultiAppMode(String jsonString) throws BundleException {
948        MultiAppMode multiAppMode = new MultiAppMode();
949        JSONObject appObj = getAppObj(jsonString);
950        JSONObject modeObj = appObj.getJSONObject(MULTI_APP_MODE);
951        if (modeObj != null) {
952            String type = modeObj.getString(MULTI_APP_MODE_TYPE);
953            Integer number = modeObj.getInteger(MULTI_APP_MODE_NUMBER);
954            multiAppMode.setMultiAppModeType(type != null ? type : "");
955            multiAppMode.setMaxCount(number != null ? number : 0);
956        }
957        return multiAppMode;
958    }
959
960    /**
961     * parse stage distroFilter.
962     *
963     * @param moduleMetadataInfos all metadata of module
964     * @return DistroFilter is the result of parsed distroFilter
965     */
966    public static DistroFilter parseStageDistroFilter(List<ModuleMetadataInfo> moduleMetadataInfos) {
967        for (ModuleMetadataInfo moduleMetadataInfo : moduleMetadataInfos) {
968            String resource = moduleMetadataInfo.resource;
969            if (resource.isEmpty()) {
970                continue;
971            }
972            JSONObject distroFilter = JSONObject.parseObject(resource);
973            if (distroFilter.containsKey(DISTRIBUTION_FILTER)) {
974                return JSONObject.parseObject(getJsonString(distroFilter, DISTRIBUTION_FILTER), DistroFilter.class);
975            }
976            if (distroFilter.containsKey(DISTRO_FILTER)) {
977                return JSONObject.parseObject(getJsonString(distroFilter, DISTRO_FILTER), DistroFilter.class);
978            }
979        }
980        return new DistroFilter();
981    }
982
983    /**
984     * parse stage parseModuleAllMetadata.
985     *
986     * @param jsonString is the string of module.json
987     * @param profileJson is the <fileName,fileString> of profile
988     * @return DistroFilter is the result of parsed distroFilter
989     */
990    public static List<ModuleMetadataInfo> parseModuleAllMetadata(
991            String jsonString, HashMap<String, String> profileJson) throws BundleException {
992        JSONObject moduleObj = getModuleObj(jsonString);
993        List<ModuleMetadataInfo> moduleMetadataInfos = new ArrayList<>();
994        if (moduleObj.containsKey(METADATA)) {
995            JSONArray metadatas = moduleObj.getJSONArray(METADATA);
996            for (int i = 0; i < metadatas.size(); ++i) {
997                JSONObject metadata = metadatas.getJSONObject(i);
998                moduleMetadataInfos.add(parseModuleMetadata(metadata, profileJson));
999            }
1000        }
1001        return moduleMetadataInfos;
1002    }
1003
1004    /**
1005     * parse metadata info
1006     *
1007     * @param jsonObject Json hap json Object
1008     * @param profileJson is the <fileName,fileString> of profile
1009     * @return the ModuleMetadataInfo result
1010     * @throws BundleException Throws this exception if the json is not standard.
1011     */
1012    public static ModuleMetadataInfo parseModuleMetadata(JSONObject jsonObject, HashMap<String, String> profileJson)
1013            throws BundleException {
1014        if (jsonObject == null) {
1015            throw new BundleException("ModuleJsonUtil::parseModuleMetadata failed, jsonObject is null.");
1016        }
1017        ModuleMetadataInfo moduleMetadataInfo = new ModuleMetadataInfo();
1018        if (jsonObject.containsKey(NAME)) {
1019            moduleMetadataInfo.name = getJsonString(jsonObject, NAME);
1020        }
1021        if (jsonObject.containsKey(VALUE)) {
1022            moduleMetadataInfo.value = getJsonString(jsonObject, VALUE);
1023        }
1024        if (jsonObject.containsKey(RESOURCE)) {
1025            moduleMetadataInfo.resource = getJsonString(jsonObject, RESOURCE);
1026            String fileName = moduleMetadataInfo.resource;
1027            fileName = fileName.replace(PROFILE, "");
1028            fileName = fileName + JSON_PERFIX;
1029            moduleMetadataInfo.resource = profileJson.get(fileName);
1030        }
1031        return moduleMetadataInfo;
1032    }
1033
1034    /**
1035     * parse metadata info
1036     *
1037     * @param jsonString Json string of config.json
1038     * @return the ModuleMetadataInfo result
1039     */
1040    public static DistroFilter parseFADistroFilter(String jsonString) throws BundleException {
1041        DistroFilter distroFilter = new DistroFilter();
1042        JSONObject jsonObj;
1043        try {
1044            jsonObj = JSON.parseObject(jsonString);
1045            if (jsonObj.containsKey(MODULE)) {
1046                JSONObject moduleObj = jsonObj.getJSONObject(MODULE);
1047                if (moduleObj.containsKey(DISTRO_FILTER)) {
1048                    distroFilter = JSONObject.parseObject(getJsonString(moduleObj,
1049                            DISTRO_FILTER), DistroFilter.class);
1050                }
1051            }
1052        } catch (JSONException exception) {
1053            String errMsg = "parse JSONObject failed: " + exception.getMessage();
1054            LOG.error(errMsg);
1055            throw new BundleException(errMsg);
1056        }
1057        return distroFilter;
1058    }
1059
1060    /**
1061     * get deviceType from json file.
1062     *
1063     * @param jsonString is the json String of module.json or config.json
1064     */
1065    public static List<String> parseDeviceType(String jsonString) throws BundleException {
1066        List<String> deviceType = new ArrayList<>();
1067        JSONObject moduleObj = getModuleObj(jsonString);
1068        if (moduleObj.containsKey(DEVICE_TYPE)) {
1069            return JSONObject.parseArray(getJsonString(moduleObj, DEVICE_TYPE), String.class);
1070        } else if (moduleObj.containsKey(DEVICE_TYPES)) {
1071            return JSONObject.parseArray(getJsonString(moduleObj, DEVICE_TYPES), String.class);
1072        } else {
1073            return deviceType;
1074        }
1075    }
1076
1077    /**
1078     * get ability names from json file.
1079     *
1080     * @param jsonString is the json String of module.json or config.json
1081     * @return ability names
1082     */
1083    public static List<String> parseAbilityNames(String jsonString) throws BundleException {
1084        List<String> abilityNames = new ArrayList<>();
1085        JSONObject moduleObj = getModuleObj(jsonString);
1086        if (moduleObj.containsKey(ABILITIES)) {
1087            JSONArray abilityObjs = moduleObj.getJSONArray(ABILITIES);
1088            for (int i = 0; i < abilityObjs.size(); ++i) {
1089                JSONObject abilityObj = abilityObjs.getJSONObject(i);
1090                if (abilityObj.containsKey(NAME)) {
1091                    abilityNames.add(getJsonString(abilityObj, NAME));
1092                }
1093            }
1094        }
1095
1096        return abilityNames;
1097    }
1098
1099    /**
1100     * get ability continueType map from json file.
1101     *
1102     * @param jsonString is the json String of module.json
1103     * @return continueType map
1104     */
1105    public static Map<String, List<String>> parseAbilityContinueTypeMap(String jsonString)
1106            throws BundleException {
1107        Map<String, List<String>> continueTypeMap = new HashMap<>();
1108        JSONObject moduleObj = getModuleObj(jsonString);
1109        if (moduleObj.containsKey(ABILITIES)) {
1110            JSONArray abilityObjs = moduleObj.getJSONArray(ABILITIES);
1111            for (int i = 0; i < abilityObjs.size(); ++i) {
1112                JSONObject abilityObj = abilityObjs.getJSONObject(i);
1113                String abilityName = getJsonString(abilityObj, NAME);
1114                if (abilityObj.containsKey(CONTINUE_TYPE)) {
1115                    JSONArray typeArray = abilityObj.getJSONArray(CONTINUE_TYPE);
1116                    continueTypeMap.put(abilityName, typeArray.toJavaList(String.class));
1117                } else {
1118                    continueTypeMap.put(abilityName, new ArrayList<>());
1119                }
1120            }
1121        }
1122        return continueTypeMap;
1123    }
1124
1125    /**
1126     * parse stage ExtensionAbility names
1127     *
1128     * @param jsonString is the json String of module.json
1129     * @return extensionAbilityNames
1130     */
1131    public static List<String> parseExtensionAbilityName(String jsonString) throws BundleException {
1132        JSONObject moduleObj = getModuleObj(jsonString);
1133        List<String> extensionAbilityNames = new ArrayList<>();
1134        if (moduleObj.containsKey(EXTENSION_ABILITIES)) {
1135            JSONArray extensionAbilityObjs = moduleObj.getJSONArray(EXTENSION_ABILITIES);
1136            for (int i = 0; i < extensionAbilityObjs.size(); ++i) {
1137                JSONObject extensionAbilityObj = extensionAbilityObjs.getJSONObject(i);
1138                if (extensionAbilityObj.containsKey(NAME)) {
1139                    extensionAbilityNames.add(getJsonString(extensionAbilityObj, NAME));
1140                }
1141            }
1142        }
1143        return extensionAbilityNames;
1144    }
1145
1146    /**
1147     * get ability skills map from json file.
1148     *
1149     * @param jsonString is the json String of module.json
1150     * @return skillsMap key is ability,value indicates whether this door is a home ability
1151     */
1152    public static Map<String, Boolean> parseAbilitySkillsMap(String jsonString)
1153            throws BundleException {
1154        Map<String, Boolean> skillsMap = new HashMap<>();
1155        JSONObject moduleObj = getModuleObj(jsonString);
1156        JSONArray abilityObs = moduleObj.getJSONArray(ABILITIES);
1157        if(abilityObs == null) {
1158            return skillsMap;
1159        }
1160        for (int i = 0; i < abilityObs.size(); ++i) {
1161            JSONObject abilityObj = abilityObs.getJSONObject(i);
1162            String abilityName = getJsonString(abilityObj, NAME);
1163            skillsMap.put(abilityName, false);
1164            if(!abilityObj.containsKey(SKILLS)) {
1165                break;
1166            }
1167            JSONArray skillArray = abilityObj.getJSONArray(SKILLS);
1168            for (int j = 0; j < skillArray.size(); ++j) {
1169                JSONObject skillObj = skillArray.getJSONObject(j);
1170                String entities = getJsonString(skillObj, SKILLS_ENTITIES);
1171                String actions = getJsonString(skillObj, SKILLS_ACTIONS);
1172                if (entities.contains(ENTITY_SYSTEM_HOME) && actions.contains(ACTION_SYSTEM_HOME)) {
1173                    skillsMap.put(abilityName, true);
1174                    break;
1175                }
1176            }
1177        }
1178        return skillsMap;
1179    }
1180
1181    /**
1182     * parse stage module type.
1183     *
1184     * @param jsonString is the json String of module.json or config.json
1185     * @return is entry
1186     */
1187    public static String parseModuleType(String jsonString) throws BundleException {
1188        JSONObject moduleObj = getModuleObj(jsonString);
1189        if (moduleObj.containsKey(TYPE)) {
1190            return getJsonString(moduleObj, TYPE);
1191        }
1192        return EMPTY_STRING;
1193    }
1194
1195    /**
1196     * parse FA module type.
1197     *
1198     * @param jsonString is the json String of module.json or config.json
1199     * @return is entry
1200     */
1201    public static String parseFAIsEntry(String jsonString) throws BundleException {
1202        JSONObject moduleObj = getModuleObj(jsonString);
1203        if (moduleObj.containsKey(DISTRO)) {
1204            JSONObject distroObj = moduleObj.getJSONObject(DISTRO);
1205            if (distroObj.containsKey(MODULE_TYPE)) {
1206                return getJsonString(distroObj, MODULE_TYPE);
1207            }
1208        }
1209        return EMPTY_STRING;
1210    }
1211
1212    static List<DependencyItem> parseDependencies(String jsonString, String bundleName) throws BundleException {
1213        JSONObject moduleObj = getModuleObj(jsonString);
1214
1215        List<DependencyItem> dependencyItemList = new ArrayList<>();
1216        if (!moduleObj.containsKey(DEPENDENCIES)) {
1217            return dependencyItemList;
1218        }
1219        JSONArray dependencyObjList = moduleObj.getJSONArray(DEPENDENCIES);
1220        for (int i = 0; i < dependencyObjList.size(); ++i) {
1221            JSONObject object = dependencyObjList.getJSONObject(i);
1222            DependencyItem item = new DependencyItem();
1223            if (object.containsKey(BUNDLE_NAME)) {
1224                item.setBundleName(object.getString(BUNDLE_NAME));
1225            } else {
1226                item.setBundleName(bundleName);
1227            }
1228            if (object.containsKey(MODULE_NAME)) {
1229                item.setModuleName(object.getString(MODULE_NAME));
1230            }
1231            dependencyItemList.add(item);
1232        }
1233        return dependencyItemList;
1234    }
1235
1236    static boolean parseStageInstallation(String jsonString) throws BundleException {
1237        JSONObject moduleObj = getModuleObj(jsonString);
1238
1239        if (moduleObj.containsKey(INSTALLATION_FREE)) {
1240            return moduleObj.getBoolean(INSTALLATION_FREE);
1241        }
1242        return false;
1243    }
1244
1245    static String parseStageBundleType(String jsonString) throws BundleException {
1246        JSONObject moduleObj = getModuleObj(jsonString);
1247        String moduleName = parseStageModuleName(jsonString);
1248        if (!moduleObj.containsKey(TYPE)) {
1249            String errMsg = "parse failed, input module.json is invalid, " +
1250                    "module.json has no type in module: " + moduleName;
1251            LOG.error(errMsg);
1252            throw new BundleException(errMsg);
1253        }
1254        String type = moduleObj.getString(TYPE);
1255        boolean installationFree = getJsonBooleanValue(moduleObj, INSTALLATION_FREE, false);
1256        JSONObject appObj = getAppObj(jsonString);
1257        if (!appObj.containsKey(BUNDLE_TYPE)) {
1258            if (installationFree) {
1259                String errMessage = "The app.json5 file configuration does not match the installationFree:" +
1260                        " true settings. Add the bundleType field to the app.json5 file and set it atomicService.";
1261                LOG.error(errMessage);
1262                throw new BundleException(errMessage);
1263            }
1264            return APP;
1265        } else {
1266            String bundleType = getJsonString(appObj, BUNDLE_TYPE);
1267            if (bundleType.equals(APP)) {
1268                if (installationFree) {
1269                    String errMsg = "installationFree must be false in module(" +
1270                            moduleName + ") when bundleType is app.";
1271                    LOG.error(errMsg);
1272                    throw new BundleException(errMsg);
1273                }
1274                return APP;
1275            } else if (bundleType.equals(ATOMIC_SERVICE)) {
1276                if (!installationFree) {
1277                    String errMsg = "installationFree must be true in module(" +
1278                            moduleName + ") when bundleType is atomicService.";
1279                    LOG.error(errMsg);
1280                    throw new BundleException(errMsg);
1281                }
1282                return ATOMIC_SERVICE;
1283            } else if (SHARED.equals(bundleType)) {
1284                if (!SHARED.equals(type)) {
1285                    String errMsg = "type must be shared in module(" + moduleName + ") when bundleType is shared.";
1286                    LOG.error(errMsg);
1287                    throw new BundleException(errMsg);
1288                }
1289                return SHARED;
1290            } else if (APP_SERVICE.equals(bundleType)) {
1291                return APP_SERVICE;
1292            } else {
1293                LOG.error("bundleType is invalid in app.json.");
1294                throw new BundleException("bundleType is invalid in app.json.");
1295            }
1296        }
1297    }
1298
1299    static List<PreloadItem> parseAtomicServicePreloads(String jsonString) throws BundleException {
1300        List<PreloadItem> preloadItems = new ArrayList<>();
1301        JSONObject moduleObj = getModuleObj(jsonString);
1302        JSONObject atomicServiceObj = null;
1303        if (!moduleObj.containsKey(ATOMIC_SERVICE)) {
1304            return preloadItems;
1305        }
1306        atomicServiceObj = moduleObj.getJSONObject(ATOMIC_SERVICE);
1307        if (!atomicServiceObj.containsKey(PRELOADS)) {
1308            return preloadItems;
1309        }
1310        JSONArray preloadObjs = atomicServiceObj.getJSONArray(PRELOADS);
1311        for (int i = 0; i < preloadObjs.size(); ++i) {
1312            PreloadItem preloadItem = new PreloadItem();
1313            JSONObject itemObj = preloadObjs.getJSONObject(i);
1314            if (itemObj.containsKey(MODULE_NAME)) {
1315                preloadItem.setModuleName(getJsonString(itemObj, MODULE_NAME));
1316            }
1317            preloadItems.add(preloadItem);
1318        }
1319        return preloadItems;
1320    }
1321
1322    static List<String> parseProxyDataUri(String jsonString) throws BundleException {
1323        List<String> proxyDataUris = new ArrayList<>();
1324        JSONObject moduleObj = getModuleObj(jsonString);
1325        if (!moduleObj.containsKey(PROXY_DATAS) && !moduleObj.containsKey(PROXY_DATA)) {
1326            return proxyDataUris;
1327        } else if (moduleObj.containsKey(PROXY_DATA)) {
1328            JSONArray proxyData = moduleObj.getJSONArray(PROXY_DATA);
1329            for (int i = 0; i < proxyData.size(); ++i) {
1330                JSONObject itemObj = proxyData.getJSONObject(i);
1331                if (!itemObj.containsKey(PROXY_URI)) {
1332                    LOG.error("parse JOSNObject failed in parseProxyDataUri.");
1333                    throw new BundleException("parse JOSNObject failed in parseProxyDataUri.");
1334                }
1335                String uri = itemObj.getString(PROXY_URI);
1336                proxyDataUris.add(uri);
1337            }
1338        } else {
1339            JSONArray proxyDatas = moduleObj.getJSONArray(PROXY_DATAS);
1340            for (int i = 0; i < proxyDatas.size(); ++i) {
1341                JSONObject itemObj = proxyDatas.getJSONObject(i);
1342                if (!itemObj.containsKey(PROXY_URI)) {
1343                    LOG.error("parse JOSNObject failed in parseProxyDataUri.");
1344                    throw new BundleException("parse JOSNObject failed in parseProxyDataUri.");
1345                }
1346                String uri = itemObj.getString(PROXY_URI);
1347                proxyDataUris.add(uri);
1348            }
1349        }
1350        return proxyDataUris;
1351    }
1352
1353    static JSONObject getAppObj(String jsonString) throws BundleException {
1354        JSONObject jsonObject;
1355        try {
1356            jsonObject = JSON.parseObject(jsonString);
1357        } catch (JSONException exception) {
1358            String errMsg = "parse JSONobject failed.";
1359            LOG.error(errMsg);
1360            throw new BundleException(errMsg);
1361        }
1362        JSONObject appObj = jsonObject.getJSONObject(APP);
1363        if (appObj == null) {
1364            LOG.error("ModuleJsonUtil::parseStageInstallation json do not contain app.");
1365            throw new BundleException("ModuleJsonUtil::parseStageInstallation json do not contain app.");
1366        }
1367        return appObj;
1368    }
1369
1370    static JSONObject getModuleObj(String jsonString) throws BundleException {
1371        JSONObject jsonObj;
1372        try {
1373            jsonObj = JSON.parseObject(jsonString);
1374        } catch (JSONException exception) {
1375            String errMsg = "parse JSONobject failed.";
1376            LOG.error(errMsg);
1377            throw new BundleException(errMsg);
1378        }
1379        if (jsonObj == null) {
1380            LOG.error("ModuleJsonUtil::parseStageInstallation jsonObj is null.");
1381            throw new BundleException("ModuleJsonUtil::parseStageInstallation jsonObj is null.");
1382        }
1383        JSONObject moduleObj = jsonObj.getJSONObject(MODULE);
1384        if (moduleObj == null) {
1385            LOG.error("ModuleJsonUtil::parseStageInstallation json do not contain module.");
1386            throw new BundleException("ModuleJsonUtil::parseStageInstallation json do not contain module.");
1387        }
1388        return moduleObj;
1389    }
1390
1391    static String parseTargetBundleName(String jsonString) throws BundleException {
1392        JSONObject appObject = getAppObj(jsonString);
1393        String targetBundleName = "";
1394        if (appObject.containsKey(TARGET_BUNDLE_NAME)) {
1395            targetBundleName = appObject.getString(TARGET_BUNDLE_NAME);
1396        }
1397        return targetBundleName;
1398    }
1399
1400    static int parseTargetPriority(String jsonString) throws BundleException {
1401        JSONObject appObject = getAppObj(jsonString);
1402        int targetPriority = 0;
1403        if (appObject.containsKey(TARGET_PRIORITY)) {
1404            targetPriority = appObject.getIntValue(TARGET_PRIORITY);
1405        }
1406        return targetPriority;
1407    }
1408
1409    static String parseTargetModuleName(String jsonString) throws BundleException {
1410        JSONObject moduleObj = getModuleObj(jsonString);
1411        String targetModuleName = "";
1412        if (moduleObj.containsKey(TARGET_MODULE_NAME)) {
1413            targetModuleName = moduleObj.getString(TARGET_MODULE_NAME);
1414        }
1415        return targetModuleName;
1416    }
1417
1418    static int parseTargetModulePriority(String jsonString) throws BundleException {
1419        JSONObject moduleObj = getModuleObj(jsonString);
1420        int targetModulePriority = 0;
1421        if (moduleObj.containsKey(TARGET_PRIORITY)) {
1422            targetModulePriority = moduleObj.getIntValue(TARGET_PRIORITY);
1423        }
1424        return targetModulePriority;
1425    }
1426
1427    static boolean parseFAInstallationFree(String jsonString) throws BundleException {
1428        JSONObject moduleObj = getModuleObj(jsonString);
1429        JSONObject distroObj = moduleObj.getJSONObject(DISTRO);
1430        if (distroObj == null) {
1431            LOG.error("ModuleJsonUtil::parseStageInstallation json do not contain distro.");
1432            throw new BundleException("ModuleJsonUtil::parseStageInstallation json do not contain distro.");
1433        }
1434        if (distroObj.containsKey(INSTALLATION_FREE)) {
1435            return distroObj.getBoolean(INSTALLATION_FREE);
1436        }
1437        return false;
1438    }
1439
1440    /**
1441     * get hqfVerifyINfo from hqf file
1442     *
1443     * @param hqfPath is the file path of hqf file
1444     * @return HQFVerifyInfo
1445     */
1446    static HQFInfo parseHQFInfo(String hqfPath) throws BundleException {
1447        File hqfFile = new File(hqfPath);
1448        String patchJson = FileUtils.getJsonInZips(hqfFile, PATCH_JSON);
1449        return parsePatch(patchJson);
1450    }
1451
1452    /**
1453     * parse patch.json form json string.
1454     *
1455     * @param jsonString is the file path of hqf file
1456     * @return HQFVerifyInfo
1457     */
1458    static HQFInfo parsePatch(String jsonString) throws BundleException {
1459        JSONObject appObj = getAppObj(jsonString);
1460        HQFInfo hqfVerifyInfo = new HQFInfo();
1461        if (appObj.containsKey(BUNDLE_NAME)) {
1462            hqfVerifyInfo.setBundleName(appObj.getString(BUNDLE_NAME));
1463        }
1464        if (appObj.containsKey(VERSIONCODE)) {
1465            hqfVerifyInfo.setVersionCode(appObj.getIntValue(VERSIONCODE));
1466        }
1467        if (appObj.containsKey(VERSIONNAME)) {
1468            hqfVerifyInfo.setVersionName(appObj.getString(VERSIONNAME));
1469        }
1470        if (appObj.containsKey(PATCH_VERSION_CODE)) {
1471            hqfVerifyInfo.setPatchVersionCode(appObj.getIntValue(PATCH_VERSION_CODE));
1472        }
1473        if (appObj.containsKey(PATCH_VERSION_NAME)) {
1474            hqfVerifyInfo.setPatchVersionName(appObj.getString(PATCH_VERSION_NAME));
1475        }
1476
1477        JSONObject moduleObj = getModuleObj(jsonString);
1478        if (moduleObj.containsKey(NAME)) {
1479            hqfVerifyInfo.setModuleName(moduleObj.getString(NAME));
1480        }
1481        if (moduleObj.containsKey(TYPE)) {
1482            hqfVerifyInfo.setType(moduleObj.getString(TYPE));
1483        }
1484        if (moduleObj.containsKey(DEVICE_TYPES)) {
1485            hqfVerifyInfo.setDeviceTypes(JSONObject.parseArray(getJsonString(moduleObj, DEVICE_TYPES), String.class));
1486        }
1487        if (moduleObj.containsKey(ORIGINAL_MODULE_HASH)) {
1488            hqfVerifyInfo.setOriginalModuleHash(moduleObj.getString(ORIGINAL_MODULE_HASH));
1489        }
1490        return hqfVerifyInfo;
1491    }
1492
1493    /**
1494     * determine whether it is a native compression libs.
1495     *
1496     * @param jsonString is the file path of hqf file
1497     * @return the result
1498     */
1499    public static boolean stageIsCompressNativeLibs(String jsonString) throws BundleException {
1500        JSONObject moduleObj = getModuleObj(jsonString);
1501        if (moduleObj.containsKey(COMPRESS_NATIVE_LIBS)) {
1502            return moduleObj.getBoolean(COMPRESS_NATIVE_LIBS);
1503        }
1504
1505        return false;
1506    }
1507
1508    /**
1509     * get asanEnabled in module.json
1510     *
1511     * @param jsonString is the file content of module.json
1512     * @return the value of asanEnabled
1513     */
1514    public static boolean getStageAsanEnabled(String jsonString) throws BundleException {
1515        JSONObject appObj = getAppObj(jsonString);
1516        if (appObj.containsKey(ASAN_ENABLED)) {
1517            return appObj.getBoolean(ASAN_ENABLED);
1518        }
1519        return false;
1520    }
1521
1522    /**
1523     * get tsanEnabled in module.json
1524     *
1525     * @param jsonString is the file content of module.json
1526     * @return the value of tsanEnabled
1527     */
1528    public static boolean getStageTsanEnabled(String jsonString) throws BundleException {
1529        JSONObject appObj = getAppObj(jsonString);
1530        if (appObj.containsKey(TSAN_ENABLED)) {
1531            return appObj.getBoolean(TSAN_ENABLED);
1532        }
1533        return false;
1534    }
1535
1536    /**
1537     * get gwpAsanEnabled in module.json
1538     *
1539     * @param jsonString is the file content of module.json
1540     * @return the value of gwpAsanEnabled
1541     */
1542    public static boolean getStageGwpAsanEnabled(String jsonString) throws BundleException {
1543        JSONObject appObj = getAppObj(jsonString);
1544        if (appObj.containsKey(GWP_ASAN_ENABLED)) {
1545            return appObj.getBoolean(GWP_ASAN_ENABLED);
1546        }
1547        return false;
1548    }
1549
1550    /**
1551     * get hwasanEnabled in module.json
1552     *
1553     * @param jsonString is the file content of module.json
1554     * @return the value of hwasanEnabled
1555     */
1556    public static boolean getStageHwasanEnabled(String jsonString) throws BundleException {
1557        JSONObject appObj = getAppObj(jsonString);
1558        if (appObj.containsKey(HW_ASAN_ENABLED)) {
1559            return appObj.getBoolean(HW_ASAN_ENABLED);
1560        }
1561        return false;
1562    }
1563
1564    /**
1565     * get ubsanEnabled in module.json
1566     *
1567     * @param jsonString is the file content of module.json
1568     * @return the value of ubsanEnabled
1569     */
1570    public static boolean getStageUbsanEnabled(String jsonString) throws BundleException {
1571        JSONObject appObj = getAppObj(jsonString);
1572        if (appObj.containsKey(UB_SAN_ENABLED)) {
1573            return appObj.getBoolean(UB_SAN_ENABLED);
1574        }
1575        return false;
1576    }
1577
1578
1579    /**
1580     * get ability continueBundleName map from json file.
1581     *
1582     * @param jsonString is the json String of module.json
1583     * @return continueBundleName map
1584     */
1585    public static Map<String, List<String>> getAbilityContinueBundleNameMap(String jsonString)
1586            throws BundleException {
1587        Map<String, List<String>> continueBundleName = new HashMap<>();
1588        JSONObject moduleObj = getModuleObj(jsonString);
1589        if (moduleObj.containsKey(ABILITIES)) {
1590            JSONArray abilityObjs = moduleObj.getJSONArray(ABILITIES);
1591            for (int i = 0; i < abilityObjs.size(); ++i) {
1592                JSONObject abilityObj = abilityObjs.getJSONObject(i);
1593                String abilityName = getJsonString(abilityObj, NAME);
1594                if (abilityObj.containsKey(CONTINUE_BUNDLE_NAME)) {
1595                    JSONArray typeArray = abilityObj.getJSONArray(CONTINUE_BUNDLE_NAME);
1596                    continueBundleName.put(abilityName, typeArray.toJavaList(String.class));
1597                } else {
1598                    continueBundleName.put(abilityName, new ArrayList<>());
1599                }
1600            }
1601        }
1602        return continueBundleName;
1603    }
1604
1605    /**
1606     * get apiReleaseType in module.json
1607     *
1608     * @param jsonString is the file content of module.json
1609     * @return the result
1610     */
1611    public static String getStageApiReleaseType(String jsonString) throws BundleException {
1612        JSONObject appObj = getAppObj(jsonString);
1613        return getJsonString(appObj, API_RELEASE_TYPE);
1614    }
1615
1616    /**
1617     * get debug in module.json
1618     *
1619     * @param jsonString is the file content of module.json
1620     * @return the result
1621     */
1622    public static boolean getDebug(String jsonString) throws BundleException {
1623        JSONObject appObj = getAppObj(jsonString);
1624
1625        return getJsonBooleanValue(appObj, DEBUG, false);
1626    }
1627
1628    /**
1629     * get debug in config.json
1630     *
1631     * @param jsonString is the file content of module.json
1632     * @return the result
1633     */
1634    public static boolean getFADebug(String jsonString) throws BundleException {
1635        JSONObject jsonObject;
1636        try {
1637            jsonObject = JSON.parseObject(jsonString);
1638        } catch (JSONException exception) {
1639            LOG.error("parse JOSNObject failed in getStageApiReleaseType.");
1640            throw new BundleException("parse JOSNObject failed in getStageApiReleaseType.");
1641        }
1642        JSONObject deviceConfigObj = jsonObject.getJSONObject(DEVICE_CONFIG);
1643        if (deviceConfigObj == null) {
1644            return false;
1645        }
1646        JSONObject defaultObj = deviceConfigObj.getJSONObject(DEFAULT);
1647        if (defaultObj == null) {
1648            return false;
1649        }
1650
1651        return getJsonBooleanValue(defaultObj, DEBUG, false);
1652    }
1653
1654    /**
1655     * get compileSdkVersion in config.json
1656     *
1657     * @param jsonString is the file content of module.json
1658     * @return the result
1659     */
1660    public static String getFACompileSdkVersion(String jsonString) throws BundleException {
1661        JSONObject appObj = getAppObj(jsonString);
1662        JSONObject apiVersionObj = appObj.getJSONObject(API_VERSION);
1663        String compileSdkVersion = "";
1664        if (apiVersionObj.containsKey(COMPILE_SDK_VERSION)) {
1665            compileSdkVersion = apiVersionObj.getString(COMPILE_SDK_VERSION);
1666        }
1667        return compileSdkVersion;
1668    }
1669
1670    /**
1671     * get compileSdkType in config.json
1672     *
1673     * @param jsonString is the file content of module.json
1674     * @return the result
1675     */
1676    public static String getFACompileSdkType(String jsonString) throws BundleException {
1677        JSONObject appObj = getAppObj(jsonString);
1678        if (!appObj.containsKey(API_VERSION)) {
1679            throw new BundleException("ModuleJsonUtil::parseFAAPIVersion json file do not contain apiVersion.");
1680        }
1681        JSONObject apiVersionObj = appObj.getJSONObject(API_VERSION);
1682        String compileSdkType = "";
1683        if (apiVersionObj.containsKey(COMPILE_SDK_TYPE)) {
1684            compileSdkType = apiVersionObj.getString(COMPILE_SDK_TYPE);
1685        }
1686        return compileSdkType;
1687    }
1688
1689    /**
1690     * get compileSdkVersion in module.json
1691     *
1692     * @param jsonString is the file content of module.json
1693     * @return the result
1694     */
1695    public static String getCompileSdkVersion(String jsonString) throws BundleException {
1696        String compileSdkVersion = "";
1697        JSONObject appObj = getAppObj(jsonString);
1698        if (appObj.containsKey(COMPILE_SDK_VERSION)) {
1699            compileSdkVersion = appObj.getString(COMPILE_SDK_VERSION);
1700        } else {
1701            LOG.warning("getCompileSdkType failed: json file do not contain module compileSdkVersion.");
1702        }
1703        return compileSdkVersion;
1704    }
1705
1706    /**
1707     * get compileSdkType in module.json
1708     *
1709     * @param jsonString is the file content of module.json
1710     * @return the result
1711     */
1712    public static String getCompileSdkType(String jsonString) throws BundleException {
1713        String compileSdkType = "";
1714        JSONObject appObj = getAppObj(jsonString);
1715        if (appObj.containsKey(COMPILE_SDK_TYPE)) {
1716            compileSdkType = appObj.getString(COMPILE_SDK_TYPE);
1717        } else {
1718            LOG.warning("getCompileSdkType failed: json file do not contain module compileSdkType.");
1719        }
1720        return compileSdkType;
1721    }
1722
1723    /**
1724     * get targetModuleName in module.json
1725     *
1726     * @param jsonString is the file content of module.json
1727     * @return the result
1728     */
1729    public static String getStageTargetModuleName(String jsonString) throws BundleException {
1730        JSONObject moduleObj = getModuleObj(jsonString);
1731        return getJsonString(moduleObj, TARGET_MODULE_NAME);
1732    }
1733
1734    /**
1735     * get targetBundleName in module.json
1736     *
1737     * @param jsonString is the file content of module.json
1738     * @return the result
1739     */
1740    public static String getStageTargetBundleName(String jsonString) throws BundleException {
1741        JSONObject appObj = getAppObj(jsonString);
1742        return getJsonString(appObj, TARGET_BUNDLE_NAME);
1743    }
1744
1745    /**
1746     * is existed requestPermission in module.json
1747     *
1748     * @param jsonString is the file content of module.json
1749     * @return the result
1750     */
1751    public static boolean isExistedStageRequestPermissions(String jsonString) throws BundleException {
1752        return isExistedProperty(jsonString, MODULE, REQUEST_PERMISSIONS);
1753    }
1754
1755    /**
1756     * is existed targetPriority in module.json
1757     *
1758     * @param jsonString is the file content of module.json
1759     * @return the result
1760     */
1761    public static boolean isExistedStageModuleTargetPriority(String jsonString) throws BundleException {
1762        return isExistedProperty(jsonString, MODULE, TARGET_PRIORITY);
1763    }
1764
1765    /**
1766     * is existed targetPriority in app.json
1767     *
1768     * @param jsonString is the file content of module.json
1769     * @return the result
1770     */
1771    public static boolean isExistedStageAppTargetPriority(String jsonString) throws BundleException {
1772        return isExistedProperty(jsonString, APP, TARGET_PRIORITY);
1773    }
1774
1775    private static boolean isExistedProperty(String jsonString, String fatherProperty,
1776                                             String childProperty) throws BundleException {
1777        JSONObject jsonObject;
1778        try {
1779            jsonObject = JSON.parseObject(jsonString);
1780        } catch (JSONException exception) {
1781            LOG.error("parse JOSNObject failed in isExistedProperty.");
1782            throw new BundleException("parse JOSNObject failed in isExistedProperty.");
1783        }
1784        JSONObject appObj = jsonObject.getJSONObject(fatherProperty);
1785        if (appObj == null) {
1786            LOG.error("parse failed, input module.json is invalid, module.json has no " + fatherProperty + ".");
1787            throw new BundleException("parse failed, input module.json is invalid, module.json has no " +
1788                    fatherProperty + ".");
1789        }
1790        return appObj.containsKey(childProperty);
1791    }
1792
1793    /**
1794     * get asanEnabled in config.json
1795     *
1796     * @param jsonString is the file content of module.json
1797     * @return the value of asanEnabled
1798     */
1799    public static boolean getFAAsanEnabled(String jsonString) throws BundleException {
1800        JSONObject appObj = getAppObj(jsonString);
1801        if (appObj.containsKey(ASAN_ENABLED)) {
1802            return appObj.getBoolean(ASAN_ENABLED);
1803        }
1804        return false;
1805    }
1806
1807    /**
1808     * get releaseType in config.json
1809     *
1810     * @param jsonString is the file content of config.json
1811     * @return the result
1812     */
1813    public static String getFAReleaseType(String jsonString) throws BundleException {
1814        JSONObject appObj = getAppObj(jsonString);
1815        JSONObject apiVersionObj = appObj.getJSONObject(API_VERSION);
1816        if (apiVersionObj == null) {
1817            return "";
1818        }
1819        return getJsonString(apiVersionObj, RELEASE_TYPE);
1820    }
1821
1822    /**
1823     * check module atomic service is valid
1824     *
1825     * @param jsonString is the file content of config.json
1826     * @return the result
1827     * @throws BundleException Throws this exception if the json is not standard.
1828     */
1829    public static boolean isModuleAtomicServiceValid(String jsonString) throws BundleException {
1830        JSONObject moduleObj = getModuleObj(jsonString);
1831        if (!moduleObj.containsKey(ATOMIC_SERVICE)) {
1832            return true;
1833        }
1834        JSONObject appObj = getAppObj(jsonString);
1835
1836        if (moduleObj.containsKey(ATOMIC_SERVICE) && (!appObj.containsKey(BUNDLE_TYPE) ||
1837                !getJsonString(appObj, BUNDLE_TYPE).equals(ATOMIC_SERVICE))) {
1838            LOG.error("module can not config atomicService when bundleType is not atomicService.");
1839            return false;
1840        }
1841        return true;
1842    }
1843
1844    /**
1845     * check entry module must contain at least one ability.
1846     *
1847     * @param jsonString Indicates the jsonString.
1848     * @return Returns true if jsonString is valid.
1849     */
1850    public static boolean checkEntryInAtomicService(String jsonString) throws BundleException {
1851        if (!parseStageBundleType(jsonString).equals(ATOMIC_SERVICE)) {
1852            return true;
1853        }
1854        if (parseModuleType(jsonString).equals(ENTRY) && parseAbilityNames(jsonString).isEmpty()) {
1855            LOG.error("entry module must contain at least one ability.");
1856            return false;
1857        }
1858        return true;
1859    }
1860
1861    /**
1862     * check module atomic installation free is valid
1863     *
1864     * @param jsonString is the file content of config.json
1865     * @return the result
1866     * @throws BundleException Throws this exception if the json is not standard.
1867     */
1868    public static boolean checkAtomicServiceInstallationFree(String jsonString) throws BundleException {
1869        JSONObject moduleObj = getModuleObj(jsonString);
1870        JSONObject appObj = getAppObj(jsonString);
1871
1872        boolean installationFree = getJsonBooleanValue(moduleObj, INSTALLATION_FREE, false);
1873        if (!appObj.containsKey(BUNDLE_TYPE)) {
1874            if (installationFree) {
1875                String errMessage = "The app.json5 file configuration does not match the installationFree:" +
1876                        " true settings. Add the bundleType field to the app.json5 file and set it atomicService.";
1877                LOG.error(errMessage);
1878                return false;
1879            }
1880            return true;
1881        }
1882        String bundleType = getJsonString(appObj, BUNDLE_TYPE);
1883        if (bundleType.equals(APP)) {
1884            if (installationFree) {
1885                LOG.error("installationFree must be false when bundleType is app.");
1886                return false;
1887            }
1888        } else if (bundleType.equals(ATOMIC_SERVICE)) {
1889            if (!installationFree) {
1890                LOG.error("installationFree must be true when bundleType is atomicService.");
1891                return false;
1892            }
1893        } else if (SHARED.equals(bundleType)) {
1894            if (installationFree) {
1895                LOG.error("installationFree must be false when bundleType is shared.");
1896                return false;
1897            }
1898        } else if (APP_SERVICE.equals(bundleType)) {
1899            if (installationFree) {
1900                LOG.error("installationFree must be false when bundleType is appService.");
1901                return false;
1902            }
1903        } else {
1904            LOG.error("bundleType is invalid in app.json.");
1905            return false;
1906        }
1907        return true;
1908    }
1909
1910    /**
1911     * get the String from JSONObject by the key.
1912     *
1913     * @param jsonObject uncompress json object
1914     * @param key value key
1915     * @return the result
1916     */
1917    private static String getJsonString(JSONObject jsonObject, String key) {
1918        String value = "";
1919        if (jsonObject != null && jsonObject.containsKey(key) && jsonObject.get(key) != null) {
1920            value = jsonObject.get(key).toString();
1921        }
1922        return value;
1923    }
1924
1925    private static boolean getJsonBooleanValue(JSONObject jsonObject, String key, boolean defaultValue) {
1926        boolean value = defaultValue;
1927        if (jsonObject != null && jsonObject.containsKey(key)) {
1928            value = jsonObject.getBooleanValue(key);
1929        }
1930        return value;
1931    }
1932
1933    private static int getCount(String str, char targetChar) {
1934        int count = 0;
1935        for (int i = 0; i < str.length(); i++) {
1936            if (str.charAt(i) == targetChar) {
1937                count++;
1938            }
1939        }
1940        return count;
1941    }
1942
1943    private static void parsePackInfoExtensionAbility(String moduleName, JSONObject moduleJson, List<String> formNameList,
1944                                              List<String> fullFormNameList) throws BundleException {
1945        if (!moduleJson.containsKey(EXTENSION_ABILITIES)) {
1946            LOG.warning("ModuleJsonUtil::parsePackInfoExtensionAbility error: summary.modules.extensionAbilities is null.");
1947            return;
1948        }
1949
1950        JSONArray extensionAbilityJsonList = moduleJson.getJSONArray(EXTENSION_ABILITIES);
1951        for (int j = 0; j < extensionAbilityJsonList.size(); j++) {
1952            JSONObject extensionAbilityJson = extensionAbilityJsonList.getJSONObject(j);
1953            if (extensionAbilityJson == null || !extensionAbilityJson.containsKey(FORMS)) {
1954                LOG.warning("ModuleJsonUtil::parsePackInfoExtensionAbility error: " +
1955                        "summary.modules.extensionAbilities.forms is null.");
1956                continue;
1957            }
1958
1959            parsePackInfoForms(moduleName, extensionAbilityJson, formNameList, fullFormNameList);
1960        }
1961    }
1962
1963    private static void parsePackInfoForms(String moduleName, JSONObject extensionAbilityJson, List<String> formNameList,
1964                                                 List<String> fullFormNameList) throws BundleException {
1965        JSONArray formJsonList = extensionAbilityJson.getJSONArray(FORMS);
1966        for (int i = 0; i < formJsonList.size(); i++) {
1967            JSONObject formObj = formJsonList.getJSONObject(i);
1968            if (formObj == null || !formObj.containsKey(NAME)) {
1969                LOG.warning("ModuleJsonUtil::parsePackInfoForms error: " +
1970                        "summary.modules.extensionAbilities.forms.name is null.");
1971                continue;
1972            }
1973
1974            String name = formObj.getString(NAME);
1975            formNameList.add(name);
1976            if (!formObj.containsKey(DEFAULTDIMENSION)) {
1977                LOG.error("ModuleJsonUtil::parsePackInfoForms exception: " +
1978                        "summary.modules.extensionAbilities.forms.defaultDimension is null.");
1979                throw new BundleException("Parse pack info defaultDimension failed, defaultDimension is null.");
1980            }
1981
1982            String defaultDimension = formObj.getString(DEFAULTDIMENSION);
1983            if (getCount(defaultDimension, '*') != 1) {
1984                LOG.error("ModuleJsonUtil::parsePackInfoForms exception: " +
1985                        "summary.modules.extensionAbilities.forms.defaultDimension is not only 1.");
1986                throw new BundleException("Parse pack info defaultDimension failed, defaultDimension is not only 1.");
1987            }
1988            if (!formObj.containsKey(SUPPORTDIMENSIONS)) {
1989                LOG.error("ModuleJsonUtil::parsePackInfoForms exception: " +
1990                        "summary.modules.extensionAbilities.forms.supportDimensions is null.");
1991                throw new BundleException("Parse pack info supportDimensions failed, supportDimensions is null.");
1992            }
1993
1994            List<String> dimensionList = JSONObject.parseArray(getJsonString(formObj, SUPPORTDIMENSIONS), String.class);
1995            for(String dimension : dimensionList) {
1996                String nameWithDimension = moduleName + "/" + name + "-" + dimension.replace("*", "x");
1997                fullFormNameList.add(nameWithDimension);
1998            }
1999        }
2000    }
2001}
2002