1b8a72a62Sopenharmony_ci/*
2b8a72a62Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
3b8a72a62Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b8a72a62Sopenharmony_ci * you may not use this file except in compliance with the License.
5b8a72a62Sopenharmony_ci * You may obtain a copy of the License at
6b8a72a62Sopenharmony_ci *
7b8a72a62Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8b8a72a62Sopenharmony_ci *
9b8a72a62Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b8a72a62Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b8a72a62Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b8a72a62Sopenharmony_ci * See the License for the specific language governing permissions and
13b8a72a62Sopenharmony_ci * limitations under the License.
14b8a72a62Sopenharmony_ci */
15b8a72a62Sopenharmony_ci
16b8a72a62Sopenharmony_cipackage ohos;
17b8a72a62Sopenharmony_ci
18b8a72a62Sopenharmony_ciimport com.alibaba.fastjson.JSON;
19b8a72a62Sopenharmony_ciimport com.alibaba.fastjson.JSONArray;
20b8a72a62Sopenharmony_ciimport com.alibaba.fastjson.JSONException;
21b8a72a62Sopenharmony_ciimport com.alibaba.fastjson.JSONObject;
22b8a72a62Sopenharmony_ciimport com.alibaba.fastjson.serializer.SerializerFeature;
23b8a72a62Sopenharmony_ciimport org.apache.commons.compress.archivers.zip.DefaultBackingStoreSupplier;
24b8a72a62Sopenharmony_ciimport org.apache.commons.compress.archivers.zip.ParallelScatterZipCreator;
25b8a72a62Sopenharmony_ciimport org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
26b8a72a62Sopenharmony_ciimport org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
27b8a72a62Sopenharmony_ciimport org.apache.commons.compress.archivers.zip.ZipFile;
28b8a72a62Sopenharmony_ciimport org.apache.commons.compress.parallel.InputStreamSupplier;
29b8a72a62Sopenharmony_ciimport org.apache.commons.compress.utils.IOUtils;
30b8a72a62Sopenharmony_ci
31b8a72a62Sopenharmony_ciimport java.io.ByteArrayInputStream;
32b8a72a62Sopenharmony_ciimport java.io.ByteArrayOutputStream;
33b8a72a62Sopenharmony_ciimport java.io.File;
34b8a72a62Sopenharmony_ciimport java.io.FileInputStream;
35b8a72a62Sopenharmony_ciimport java.io.IOException;
36b8a72a62Sopenharmony_ciimport java.io.InputStream;
37b8a72a62Sopenharmony_ciimport java.nio.file.FileVisitResult;
38b8a72a62Sopenharmony_ciimport java.nio.file.Files;
39b8a72a62Sopenharmony_ciimport java.nio.file.Path;
40b8a72a62Sopenharmony_ciimport java.nio.file.Paths;
41b8a72a62Sopenharmony_ciimport java.nio.file.SimpleFileVisitor;
42b8a72a62Sopenharmony_ciimport java.nio.file.attribute.BasicFileAttributes;
43b8a72a62Sopenharmony_ciimport java.security.MessageDigest;
44b8a72a62Sopenharmony_ciimport java.security.NoSuchAlgorithmException;
45b8a72a62Sopenharmony_ciimport java.util.ArrayList;
46b8a72a62Sopenharmony_ciimport java.util.Enumeration;
47b8a72a62Sopenharmony_ciimport java.util.HashSet;
48b8a72a62Sopenharmony_ciimport java.util.List;
49b8a72a62Sopenharmony_ciimport java.util.Locale;
50b8a72a62Sopenharmony_ciimport java.util.Set;
51b8a72a62Sopenharmony_ciimport java.util.concurrent.ExecutionException;
52b8a72a62Sopenharmony_ciimport java.util.concurrent.LinkedBlockingQueue;
53b8a72a62Sopenharmony_ciimport java.util.concurrent.ThreadPoolExecutor;
54b8a72a62Sopenharmony_ciimport java.util.concurrent.TimeUnit;
55b8a72a62Sopenharmony_ciimport java.util.stream.Stream;
56b8a72a62Sopenharmony_ciimport java.util.zip.CRC32;
57b8a72a62Sopenharmony_ciimport java.util.zip.CheckedOutputStream;
58b8a72a62Sopenharmony_ciimport java.util.zip.ZipEntry;
59b8a72a62Sopenharmony_ciimport java.util.zip.ZipOutputStream;
60b8a72a62Sopenharmony_ci
61b8a72a62Sopenharmony_ci/**
62b8a72a62Sopenharmony_ci * PackageUtil
63b8a72a62Sopenharmony_ci *
64b8a72a62Sopenharmony_ci * @since 2024-06-18
65b8a72a62Sopenharmony_ci */
66b8a72a62Sopenharmony_cipublic class PackageUtil {
67b8a72a62Sopenharmony_ci    private static final Log LOG = new Log("");
68b8a72a62Sopenharmony_ci
69b8a72a62Sopenharmony_ci    /**
70b8a72a62Sopenharmony_ci     * get the package name list from pack.info
71b8a72a62Sopenharmony_ci     *
72b8a72a62Sopenharmony_ci     * @param path the path dir or hsp contains pack.info, or the path of pack.info
73b8a72a62Sopenharmony_ci     * @return the list of package name
74b8a72a62Sopenharmony_ci     */
75b8a72a62Sopenharmony_ci    public static List<String> getPackageNameFromPath(Path path) {
76b8a72a62Sopenharmony_ci        List<String> list = new ArrayList<>();
77b8a72a62Sopenharmony_ci        if (!Files.exists(path)) {
78b8a72a62Sopenharmony_ci            LOG.warning("getPackageNameFromPath path not exists: " + path);
79b8a72a62Sopenharmony_ci            return list;
80b8a72a62Sopenharmony_ci        }
81b8a72a62Sopenharmony_ci        if (Files.isRegularFile(path)) {
82b8a72a62Sopenharmony_ci            String filename = path.getFileName().toString();
83b8a72a62Sopenharmony_ci            if (filename.endsWith(Constants.HSP_SUFFIX)) {
84b8a72a62Sopenharmony_ci                // .hsp: return filename
85b8a72a62Sopenharmony_ci                list.add(filename.substring(0, filename.lastIndexOf(Constants.HSP_SUFFIX)));
86b8a72a62Sopenharmony_ci                return list;
87b8a72a62Sopenharmony_ci            }
88b8a72a62Sopenharmony_ci        }
89b8a72a62Sopenharmony_ci        String content = getPackInfoContentFromPath(path);
90b8a72a62Sopenharmony_ci        if (content == null) {
91b8a72a62Sopenharmony_ci            return list;
92b8a72a62Sopenharmony_ci        }
93b8a72a62Sopenharmony_ci        return getPackageNameFromPackInfo(content);
94b8a72a62Sopenharmony_ci    }
95b8a72a62Sopenharmony_ci
96b8a72a62Sopenharmony_ci    /**
97b8a72a62Sopenharmony_ci     * get the package name list from module.json
98b8a72a62Sopenharmony_ci     *
99b8a72a62Sopenharmony_ci     * @param path the path dir or hsp contains module.json, or the path of module.json
100b8a72a62Sopenharmony_ci     * @return the bundleType
101b8a72a62Sopenharmony_ci     */
102b8a72a62Sopenharmony_ci    public static String getBundleTypeFromPath(Path path) {
103b8a72a62Sopenharmony_ci        if (!Files.exists(path)) {
104b8a72a62Sopenharmony_ci            LOG.warning("getBundleTypeFromPath path not exists: " + path);
105b8a72a62Sopenharmony_ci            return "";
106b8a72a62Sopenharmony_ci        }
107b8a72a62Sopenharmony_ci        String content = getModuleJsonContentFromPath(path);
108b8a72a62Sopenharmony_ci        if (content == null) {
109b8a72a62Sopenharmony_ci            return "";
110b8a72a62Sopenharmony_ci        }
111b8a72a62Sopenharmony_ci        return getBundleTypeFromModuleJson(content);
112b8a72a62Sopenharmony_ci    }
113b8a72a62Sopenharmony_ci
114b8a72a62Sopenharmony_ci    /**
115b8a72a62Sopenharmony_ci     * get the package name list from pack.info
116b8a72a62Sopenharmony_ci     *
117b8a72a62Sopenharmony_ci     * @param packInfoContent the content of pack.info
118b8a72a62Sopenharmony_ci     * @return the list of package name
119b8a72a62Sopenharmony_ci     */
120b8a72a62Sopenharmony_ci    public static List<String> getPackageNameFromPackInfo(String packInfoContent) {
121b8a72a62Sopenharmony_ci        List<String> packages = new ArrayList<>();
122b8a72a62Sopenharmony_ci        try {
123b8a72a62Sopenharmony_ci            JSONObject jsonObject = JSON.parseObject(packInfoContent, JSONObject.class);
124b8a72a62Sopenharmony_ci            if (jsonObject == null) {
125b8a72a62Sopenharmony_ci                LOG.warning("getPackagesFromPackInfo failed, json format invalid.");
126b8a72a62Sopenharmony_ci                return packages;
127b8a72a62Sopenharmony_ci            }
128b8a72a62Sopenharmony_ci            JSONArray jsonArray = jsonObject.getJSONArray(Constants.PACKAGES);
129b8a72a62Sopenharmony_ci            if (jsonArray == null) {
130b8a72a62Sopenharmony_ci                LOG.warning("getPackagesFromPackInfo failed, json format invalid.");
131b8a72a62Sopenharmony_ci                return packages;
132b8a72a62Sopenharmony_ci            }
133b8a72a62Sopenharmony_ci            for (int i = 0; i < jsonArray.size(); i++) {
134b8a72a62Sopenharmony_ci                JSONObject object = jsonArray.getJSONObject(i);
135b8a72a62Sopenharmony_ci                String packageName = object.getString(Constants.MODULE_NAME);
136b8a72a62Sopenharmony_ci                if (packageName != null) {
137b8a72a62Sopenharmony_ci                    packages.add(packageName);
138b8a72a62Sopenharmony_ci                }
139b8a72a62Sopenharmony_ci            }
140b8a72a62Sopenharmony_ci            return packages;
141b8a72a62Sopenharmony_ci        } catch (JSONException ex) {
142b8a72a62Sopenharmony_ci            LOG.warning("getPackagesFromPackInfo err: " + ex.getMessage());
143b8a72a62Sopenharmony_ci            return new ArrayList<>();
144b8a72a62Sopenharmony_ci        }
145b8a72a62Sopenharmony_ci    }
146b8a72a62Sopenharmony_ci
147b8a72a62Sopenharmony_ci    private static String getBundleTypeFromModuleJson(String moduleJsonContent) {
148b8a72a62Sopenharmony_ci        try {
149b8a72a62Sopenharmony_ci            JSONObject jsonObject = JSON.parseObject(moduleJsonContent, JSONObject.class);
150b8a72a62Sopenharmony_ci            if (jsonObject == null) {
151b8a72a62Sopenharmony_ci                LOG.warning("getBundleTypeFromModuleJson failed, parse json is null.");
152b8a72a62Sopenharmony_ci                return "";
153b8a72a62Sopenharmony_ci            }
154b8a72a62Sopenharmony_ci            JSONObject appObject = jsonObject.getJSONObject(Constants.APP);
155b8a72a62Sopenharmony_ci            if (appObject == null) {
156b8a72a62Sopenharmony_ci                LOG.warning("getBundleTypeFromModuleJson failed, [app] is null.");
157b8a72a62Sopenharmony_ci                return "";
158b8a72a62Sopenharmony_ci            }
159b8a72a62Sopenharmony_ci            String bundleType = appObject.getString(Constants.BUNDLE_TYPE);
160b8a72a62Sopenharmony_ci            return bundleType != null ? bundleType : Constants.APP;
161b8a72a62Sopenharmony_ci        } catch (JSONException ex) {
162b8a72a62Sopenharmony_ci            LOG.warning("getBundleTypeFromModuleJson failed: " + ex.getMessage());
163b8a72a62Sopenharmony_ci        }
164b8a72a62Sopenharmony_ci        return "";
165b8a72a62Sopenharmony_ci    }
166b8a72a62Sopenharmony_ci
167b8a72a62Sopenharmony_ci    private static ModuleJsonInfo parseModuleJsonInfo(Path moduleJson) {
168b8a72a62Sopenharmony_ci        ModuleJsonInfo moduleJsonInfo = new ModuleJsonInfo();
169b8a72a62Sopenharmony_ci        try (FileInputStream input = new FileInputStream(moduleJson.toFile())) {
170b8a72a62Sopenharmony_ci            JSONObject jsonObject = JSON.parseObject(input, JSONObject.class);
171b8a72a62Sopenharmony_ci            if (jsonObject == null) {
172b8a72a62Sopenharmony_ci                LOG.warning("parseModuleJsonInfo failed, json format invalid.");
173b8a72a62Sopenharmony_ci                return moduleJsonInfo;
174b8a72a62Sopenharmony_ci            }
175b8a72a62Sopenharmony_ci            JSONObject appObject = jsonObject.getJSONObject(Constants.APP);
176b8a72a62Sopenharmony_ci            if (appObject == null) {
177b8a72a62Sopenharmony_ci                LOG.warning("parseModuleJsonInfo failed, not found [app]");
178b8a72a62Sopenharmony_ci                return moduleJsonInfo;
179b8a72a62Sopenharmony_ci            }
180b8a72a62Sopenharmony_ci            JSONObject moduleObject = jsonObject.getJSONObject(Constants.MODULE);
181b8a72a62Sopenharmony_ci            if (moduleObject == null) {
182b8a72a62Sopenharmony_ci                LOG.warning("parseModuleJsonInfo failed, not found [module]");
183b8a72a62Sopenharmony_ci                return moduleJsonInfo;
184b8a72a62Sopenharmony_ci            }
185b8a72a62Sopenharmony_ci            moduleJsonInfo.setGenerateBuildHash(
186b8a72a62Sopenharmony_ci                    appObject.getBooleanValue(Constants.GENERATE_BUILD_HASH) ||
187b8a72a62Sopenharmony_ci                    moduleObject.getBooleanValue(Constants.GENERATE_BUILD_HASH));
188b8a72a62Sopenharmony_ci            moduleJsonInfo.setCompressNativeLibs(
189b8a72a62Sopenharmony_ci                    moduleObject.getBooleanValue(Constants.COMPRESS_NATIVE_LIBS));
190b8a72a62Sopenharmony_ci            String moduleType = moduleObject.getString(Constants.MODULE_TYPE);
191b8a72a62Sopenharmony_ci            moduleJsonInfo.setModuleType(moduleType != null ? moduleType : "");
192b8a72a62Sopenharmony_ci            String moduleName = moduleObject.getString(Constants.MODULE_NAME);
193b8a72a62Sopenharmony_ci            moduleJsonInfo.setModuleName(moduleName != null ? moduleName : "");
194b8a72a62Sopenharmony_ci            return moduleJsonInfo;
195b8a72a62Sopenharmony_ci        } catch (IOException ex) {
196b8a72a62Sopenharmony_ci            LOG.warning("parseModuleJsonInfo err: " + ex.getMessage());
197b8a72a62Sopenharmony_ci        }
198b8a72a62Sopenharmony_ci        return moduleJsonInfo;
199b8a72a62Sopenharmony_ci    }
200b8a72a62Sopenharmony_ci
201b8a72a62Sopenharmony_ci    private static String getPackInfoContentFromPath(Path path) {
202b8a72a62Sopenharmony_ci        try {
203b8a72a62Sopenharmony_ci            if (Files.isRegularFile(path)) {
204b8a72a62Sopenharmony_ci                String filename = path.getFileName().toString();
205b8a72a62Sopenharmony_ci                if (filename.equals(Constants.FILE_PACK_INFO)) {
206b8a72a62Sopenharmony_ci                    return new String(Files.readAllBytes(path));
207b8a72a62Sopenharmony_ci                } else if (filename.endsWith(Constants.HSP_SUFFIX)) {
208b8a72a62Sopenharmony_ci                    return getZipEntryContent(path, Constants.FILE_PACK_INFO);
209b8a72a62Sopenharmony_ci                }
210b8a72a62Sopenharmony_ci            } else {
211b8a72a62Sopenharmony_ci                return new String(Files.readAllBytes(path.resolve(Constants.FILE_PACK_INFO)));
212b8a72a62Sopenharmony_ci            }
213b8a72a62Sopenharmony_ci        } catch (IOException ex) {
214b8a72a62Sopenharmony_ci            LOG.warning("getPackInfoContentFromPath err: " + ex.getMessage());
215b8a72a62Sopenharmony_ci        }
216b8a72a62Sopenharmony_ci        return null;
217b8a72a62Sopenharmony_ci    }
218b8a72a62Sopenharmony_ci
219b8a72a62Sopenharmony_ci    private static String getModuleJsonContentFromPath(Path path) {
220b8a72a62Sopenharmony_ci        try {
221b8a72a62Sopenharmony_ci            if (Files.isRegularFile(path)) {
222b8a72a62Sopenharmony_ci                String filename = path.getFileName().toString();
223b8a72a62Sopenharmony_ci                if (filename.equals(Constants.FILE_MODULE_JSON)) {
224b8a72a62Sopenharmony_ci                    return new String(Files.readAllBytes(path));
225b8a72a62Sopenharmony_ci                } else if (filename.endsWith(Constants.HSP_SUFFIX)) {
226b8a72a62Sopenharmony_ci                    return getZipEntryContent(path, Constants.FILE_MODULE_JSON);
227b8a72a62Sopenharmony_ci                }
228b8a72a62Sopenharmony_ci            } else {
229b8a72a62Sopenharmony_ci                return new String(Files.readAllBytes(path.resolve(Constants.FILE_MODULE_JSON)));
230b8a72a62Sopenharmony_ci            }
231b8a72a62Sopenharmony_ci        } catch (IOException ex) {
232b8a72a62Sopenharmony_ci            LOG.warning("getPackInfoContentFromPath err: " + ex.getMessage());
233b8a72a62Sopenharmony_ci        }
234b8a72a62Sopenharmony_ci        return null;
235b8a72a62Sopenharmony_ci    }
236b8a72a62Sopenharmony_ci
237b8a72a62Sopenharmony_ci    private static String getZipEntryContent(Path zipPath, String entryName) {
238b8a72a62Sopenharmony_ci        if (!Files.isRegularFile(zipPath)) {
239b8a72a62Sopenharmony_ci            return null;
240b8a72a62Sopenharmony_ci        }
241b8a72a62Sopenharmony_ci        try (ZipFile zipFile = new ZipFile(zipPath.toFile());
242b8a72a62Sopenharmony_ci            ByteArrayOutputStream output = new ByteArrayOutputStream()) {
243b8a72a62Sopenharmony_ci            ZipArchiveEntry zipEntry = zipFile.getEntry(entryName);
244b8a72a62Sopenharmony_ci            if (zipEntry != null) {
245b8a72a62Sopenharmony_ci                IOUtils.copy(zipFile.getInputStream(zipEntry), output);
246b8a72a62Sopenharmony_ci                return output.toString();
247b8a72a62Sopenharmony_ci            }
248b8a72a62Sopenharmony_ci        } catch (IOException ex) {
249b8a72a62Sopenharmony_ci            LOG.warning("getZipEntryContent err: " + ex.getMessage());
250b8a72a62Sopenharmony_ci        }
251b8a72a62Sopenharmony_ci        return null;
252b8a72a62Sopenharmony_ci    }
253b8a72a62Sopenharmony_ci
254b8a72a62Sopenharmony_ci    /**
255b8a72a62Sopenharmony_ci     * pack hap or hsp
256b8a72a62Sopenharmony_ci     *
257b8a72a62Sopenharmony_ci     * @param inputPath     input hap/hsp path
258b8a72a62Sopenharmony_ci     * @param appPackInfo   app scope pack.info
259b8a72a62Sopenharmony_ci     * @param outPath       output dir
260b8a72a62Sopenharmony_ci     * @param compressLevel compress level
261b8a72a62Sopenharmony_ci     * @return the hap/hsp path
262b8a72a62Sopenharmony_ci     * @throws BundleException bundle exception
263b8a72a62Sopenharmony_ci     * @throws IOException IO exception
264b8a72a62Sopenharmony_ci     */
265b8a72a62Sopenharmony_ci    public static Path pack(Path inputPath, Path appPackInfo, Path outPath, int compressLevel)
266b8a72a62Sopenharmony_ci            throws BundleException, IOException {
267b8a72a62Sopenharmony_ci        if (!Files.exists(inputPath)) {
268b8a72a62Sopenharmony_ci            throw new BundleException("pack err, input path not exists.");
269b8a72a62Sopenharmony_ci        }
270b8a72a62Sopenharmony_ci        if (!Files.exists(appPackInfo)) {
271b8a72a62Sopenharmony_ci            throw new BundleException("pack err, app pack.info not exists.");
272b8a72a62Sopenharmony_ci        }
273b8a72a62Sopenharmony_ci        if (Files.isDirectory(inputPath)) {
274b8a72a62Sopenharmony_ci            return packDir(inputPath, appPackInfo, outPath, compressLevel);
275b8a72a62Sopenharmony_ci        } else if (Files.isRegularFile(inputPath) &&
276b8a72a62Sopenharmony_ci                inputPath.getFileName().toString().endsWith(Constants.HSP_SUFFIX)) {
277b8a72a62Sopenharmony_ci            return repackHsp(inputPath, appPackInfo, outPath, compressLevel);
278b8a72a62Sopenharmony_ci        }
279b8a72a62Sopenharmony_ci        throw new BundleException("pack err, not support: " + inputPath);
280b8a72a62Sopenharmony_ci    }
281b8a72a62Sopenharmony_ci
282b8a72a62Sopenharmony_ci    /**
283b8a72a62Sopenharmony_ci     * rm dir
284b8a72a62Sopenharmony_ci     *
285b8a72a62Sopenharmony_ci     * @param dir input path to rm
286b8a72a62Sopenharmony_ci     * @return true if rm dir success
287b8a72a62Sopenharmony_ci     */
288b8a72a62Sopenharmony_ci    public static boolean rmdir(Path dir) {
289b8a72a62Sopenharmony_ci        try {
290b8a72a62Sopenharmony_ci            Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
291b8a72a62Sopenharmony_ci                @Override
292b8a72a62Sopenharmony_ci                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
293b8a72a62Sopenharmony_ci                    Files.delete(file);
294b8a72a62Sopenharmony_ci                    return FileVisitResult.CONTINUE;
295b8a72a62Sopenharmony_ci                }
296b8a72a62Sopenharmony_ci
297b8a72a62Sopenharmony_ci                @Override
298b8a72a62Sopenharmony_ci                public FileVisitResult postVisitDirectory(Path dir, IOException ex) throws IOException {
299b8a72a62Sopenharmony_ci                    Files.delete(dir);
300b8a72a62Sopenharmony_ci                    return FileVisitResult.CONTINUE;
301b8a72a62Sopenharmony_ci                }
302b8a72a62Sopenharmony_ci            });
303b8a72a62Sopenharmony_ci            return true;
304b8a72a62Sopenharmony_ci        } catch (IOException ex) {
305b8a72a62Sopenharmony_ci            LOG.warning("rmdir err: " + ex.getMessage());
306b8a72a62Sopenharmony_ci        }
307b8a72a62Sopenharmony_ci        return false;
308b8a72a62Sopenharmony_ci    }
309b8a72a62Sopenharmony_ci
310b8a72a62Sopenharmony_ci    private static String hash(Path path) {
311b8a72a62Sopenharmony_ci        try (Stream<Path> pathStream = Files.walk(path)) {
312b8a72a62Sopenharmony_ci            MessageDigest md = MessageDigest.getInstance(Constants.SHA_256);
313b8a72a62Sopenharmony_ci            pathStream.filter(Files::isRegularFile)
314b8a72a62Sopenharmony_ci                    .sorted()
315b8a72a62Sopenharmony_ci                    .forEach(file -> {
316b8a72a62Sopenharmony_ci                        try {
317b8a72a62Sopenharmony_ci                            byte[] fileBytes = Files.readAllBytes(file);
318b8a72a62Sopenharmony_ci                            md.update(fileBytes);
319b8a72a62Sopenharmony_ci                        } catch (IOException e) {
320b8a72a62Sopenharmony_ci                            LOG.warning("calc hash err: " + e.getMessage());
321b8a72a62Sopenharmony_ci                        }
322b8a72a62Sopenharmony_ci                    });
323b8a72a62Sopenharmony_ci            byte[] hashBytes = md.digest();
324b8a72a62Sopenharmony_ci            StringBuilder sb = new StringBuilder();
325b8a72a62Sopenharmony_ci            for (byte b : hashBytes) {
326b8a72a62Sopenharmony_ci                sb.append(String.format("%02x", b));
327b8a72a62Sopenharmony_ci            }
328b8a72a62Sopenharmony_ci            return sb.toString();
329b8a72a62Sopenharmony_ci        } catch (NoSuchAlgorithmException | IOException e) {
330b8a72a62Sopenharmony_ci            LOG.warning("calc hash err: " + e.getMessage());
331b8a72a62Sopenharmony_ci        }
332b8a72a62Sopenharmony_ci        return "";
333b8a72a62Sopenharmony_ci    }
334b8a72a62Sopenharmony_ci
335b8a72a62Sopenharmony_ci    private static Path repackHsp(Path inputPath, Path appPackInfo, Path outPath, int compressLevel)
336b8a72a62Sopenharmony_ci            throws BundleException, IOException {
337b8a72a62Sopenharmony_ci        Path outHsp = Files.createFile(outPath.resolve(inputPath.getFileName()));
338b8a72a62Sopenharmony_ci        try (ZipFile hspFile = new ZipFile(inputPath.toFile());
339b8a72a62Sopenharmony_ci             ZipArchiveOutputStream zipOut = new ZipArchiveOutputStream(
340b8a72a62Sopenharmony_ci                     new CheckedOutputStream(Files.newOutputStream(outHsp), new CRC32()))) {
341b8a72a62Sopenharmony_ci            int cores = Runtime.getRuntime().availableProcessors();
342b8a72a62Sopenharmony_ci            ThreadPoolExecutor executorService = new ThreadPoolExecutor(cores, cores, 60L,
343b8a72a62Sopenharmony_ci                    TimeUnit.SECONDS, new LinkedBlockingQueue<>());
344b8a72a62Sopenharmony_ci            ParallelScatterZipCreator zipCreator = new ParallelScatterZipCreator(
345b8a72a62Sopenharmony_ci                    executorService, new DefaultBackingStoreSupplier(null), compressLevel);
346b8a72a62Sopenharmony_ci            // pack.info
347b8a72a62Sopenharmony_ci            pathToZipEntry(appPackInfo, Constants.NULL_DIR, zipCreator, false);
348b8a72a62Sopenharmony_ci            // others
349b8a72a62Sopenharmony_ci            Enumeration<ZipArchiveEntry> entries = hspFile.getEntries();
350b8a72a62Sopenharmony_ci            while (entries.hasMoreElements()) {
351b8a72a62Sopenharmony_ci                ZipArchiveEntry zipEntry = entries.nextElement();
352b8a72a62Sopenharmony_ci                if (Constants.FILE_PACK_INFO.equals(zipEntry.getName())) {
353b8a72a62Sopenharmony_ci                    continue;
354b8a72a62Sopenharmony_ci                }
355b8a72a62Sopenharmony_ci                InputStreamSupplier supplier = () -> {
356b8a72a62Sopenharmony_ci                    try {
357b8a72a62Sopenharmony_ci                        return hspFile.getInputStream(zipEntry);
358b8a72a62Sopenharmony_ci                    } catch (IOException e) {
359b8a72a62Sopenharmony_ci                        LOG.error("addArchiveEntry err: " + e.getMessage());
360b8a72a62Sopenharmony_ci                        return null;
361b8a72a62Sopenharmony_ci                    }
362b8a72a62Sopenharmony_ci                };
363b8a72a62Sopenharmony_ci                zipCreator.addArchiveEntry(zipEntry, supplier);
364b8a72a62Sopenharmony_ci            }
365b8a72a62Sopenharmony_ci            zipCreator.writeTo(zipOut);
366b8a72a62Sopenharmony_ci        } catch (InterruptedException | ExecutionException e) {
367b8a72a62Sopenharmony_ci            String errMsg = "repackHsp err: " + e.getMessage();
368b8a72a62Sopenharmony_ci            LOG.error(errMsg);
369b8a72a62Sopenharmony_ci            throw new BundleException(errMsg);
370b8a72a62Sopenharmony_ci        }
371b8a72a62Sopenharmony_ci        return outHsp;
372b8a72a62Sopenharmony_ci    }
373b8a72a62Sopenharmony_ci
374b8a72a62Sopenharmony_ci    private static Path packDir(Path inputPath, Path appPackInfo, Path outPath, int compressLevel)
375b8a72a62Sopenharmony_ci            throws BundleException, IOException {
376b8a72a62Sopenharmony_ci        List<String> packageNames = getPackageNameFromPath(inputPath.resolve(Constants.FILE_PACK_INFO));
377b8a72a62Sopenharmony_ci        if (packageNames.size() != 1) {
378b8a72a62Sopenharmony_ci            throw new BundleException("pack err, pack.info format err");
379b8a72a62Sopenharmony_ci        }
380b8a72a62Sopenharmony_ci        ModuleJsonInfo moduleJsonInfo = parseModuleJsonInfo(inputPath.resolve(Constants.FILE_MODULE_JSON));
381b8a72a62Sopenharmony_ci        String pkgName = packageNames.get(0);
382b8a72a62Sopenharmony_ci        String suffix = moduleJsonInfo.isShared() ? Constants.HSP_SUFFIX : Constants.HAP_SUFFIX;
383b8a72a62Sopenharmony_ci        Path outHap = Files.createFile(outPath.resolve(pkgName + suffix));
384b8a72a62Sopenharmony_ci
385b8a72a62Sopenharmony_ci        if (moduleJsonInfo.isCompressNativeLibs()) {
386b8a72a62Sopenharmony_ci            return packMultiThread(inputPath, appPackInfo, outHap, compressLevel, moduleJsonInfo);
387b8a72a62Sopenharmony_ci        } else {
388b8a72a62Sopenharmony_ci            return packSingleThread(inputPath, appPackInfo, outHap, moduleJsonInfo);
389b8a72a62Sopenharmony_ci        }
390b8a72a62Sopenharmony_ci    }
391b8a72a62Sopenharmony_ci
392b8a72a62Sopenharmony_ci    private static Path packSingleThread(Path inputPath, Path appPackInfo, Path outHap, ModuleJsonInfo moduleJsonInfo)
393b8a72a62Sopenharmony_ci            throws BundleException, IOException {
394b8a72a62Sopenharmony_ci        File[] files = inputPath.toFile().listFiles();
395b8a72a62Sopenharmony_ci        if (files == null || files.length == 0) {
396b8a72a62Sopenharmony_ci            throw new BundleException("pack err, dir is empty");
397b8a72a62Sopenharmony_ci        }
398b8a72a62Sopenharmony_ci        try (ZipOutputStream zipOut = new ZipOutputStream(
399b8a72a62Sopenharmony_ci                new CheckedOutputStream(Files.newOutputStream(outHap), new CRC32()))) {
400b8a72a62Sopenharmony_ci            // pack.info
401b8a72a62Sopenharmony_ci            pathToZipEntry(appPackInfo, Constants.NULL_DIR, zipOut, false);
402b8a72a62Sopenharmony_ci            // module.json generateBuildHash
403b8a72a62Sopenharmony_ci            if (moduleJsonInfo.isGenerateBuildHash()) {
404b8a72a62Sopenharmony_ci                genBuildHash(inputPath, zipOut);
405b8a72a62Sopenharmony_ci            }
406b8a72a62Sopenharmony_ci            // others
407b8a72a62Sopenharmony_ci            filesToZipEntry(files, zipOut, moduleJsonInfo.isGenerateBuildHash(),
408b8a72a62Sopenharmony_ci                    moduleJsonInfo.isCompressNativeLibs());
409b8a72a62Sopenharmony_ci        }
410b8a72a62Sopenharmony_ci        return outHap;
411b8a72a62Sopenharmony_ci    }
412b8a72a62Sopenharmony_ci
413b8a72a62Sopenharmony_ci    private static Path packMultiThread(Path inputPath, Path appPackInfo, Path outHap, int compressLevel,
414b8a72a62Sopenharmony_ci                                        ModuleJsonInfo moduleJsonInfo)throws BundleException, IOException {
415b8a72a62Sopenharmony_ci        File[] files = inputPath.toFile().listFiles();
416b8a72a62Sopenharmony_ci        if (files == null || files.length == 0) {
417b8a72a62Sopenharmony_ci            throw new BundleException("pack err, dir is empty");
418b8a72a62Sopenharmony_ci        }
419b8a72a62Sopenharmony_ci        try (ZipArchiveOutputStream zipOut = new ZipArchiveOutputStream(
420b8a72a62Sopenharmony_ci                new CheckedOutputStream(Files.newOutputStream(outHap), new CRC32()))) {
421b8a72a62Sopenharmony_ci            int cores = Runtime.getRuntime().availableProcessors();
422b8a72a62Sopenharmony_ci            ThreadPoolExecutor executorService = new ThreadPoolExecutor(cores, cores, 60L,
423b8a72a62Sopenharmony_ci                    TimeUnit.SECONDS, new LinkedBlockingQueue<>());
424b8a72a62Sopenharmony_ci            ParallelScatterZipCreator zipCreator = new ParallelScatterZipCreator(
425b8a72a62Sopenharmony_ci                    executorService, new DefaultBackingStoreSupplier(null), compressLevel);
426b8a72a62Sopenharmony_ci            // pack.info
427b8a72a62Sopenharmony_ci            pathToZipEntry(appPackInfo, Constants.NULL_DIR, zipCreator, false);
428b8a72a62Sopenharmony_ci            // module.json generateBuildHash
429b8a72a62Sopenharmony_ci            if (moduleJsonInfo.isGenerateBuildHash()) {
430b8a72a62Sopenharmony_ci                genBuildHash(inputPath, zipCreator);
431b8a72a62Sopenharmony_ci            }
432b8a72a62Sopenharmony_ci            // others
433b8a72a62Sopenharmony_ci            filesToZipEntry(files, zipCreator, moduleJsonInfo.isGenerateBuildHash(),
434b8a72a62Sopenharmony_ci                    moduleJsonInfo.isCompressNativeLibs());
435b8a72a62Sopenharmony_ci            // write to zip
436b8a72a62Sopenharmony_ci            zipCreator.writeTo(zipOut);
437b8a72a62Sopenharmony_ci        } catch (InterruptedException | ExecutionException e) {
438b8a72a62Sopenharmony_ci            String errMsg = "packDir err: " + e.getMessage();
439b8a72a62Sopenharmony_ci            LOG.error(errMsg);
440b8a72a62Sopenharmony_ci            throw new BundleException(errMsg);
441b8a72a62Sopenharmony_ci        }
442b8a72a62Sopenharmony_ci        return outHap;
443b8a72a62Sopenharmony_ci    }
444b8a72a62Sopenharmony_ci
445b8a72a62Sopenharmony_ci    private static void filesToZipEntry(File[] files, ParallelScatterZipCreator zipCreator,
446b8a72a62Sopenharmony_ci                                        boolean genHash, boolean compress) throws BundleException {
447b8a72a62Sopenharmony_ci        for (File file : files) {
448b8a72a62Sopenharmony_ci            if (file.isFile() && !file.getName().equals(Constants.FILE_PACK_INFO)) {
449b8a72a62Sopenharmony_ci                if (genHash && file.getName().equals(Constants.FILE_MODULE_JSON)) {
450b8a72a62Sopenharmony_ci                    continue;
451b8a72a62Sopenharmony_ci                }
452b8a72a62Sopenharmony_ci                pathToZipEntry(file.toPath(), Constants.NULL_DIR, zipCreator, false);
453b8a72a62Sopenharmony_ci            } else if (file.isDirectory()) {
454b8a72a62Sopenharmony_ci                if (file.getName().equals(Constants.LIBS_DIR)) {
455b8a72a62Sopenharmony_ci                    pathToZipEntry(file.toPath(), Constants.LIBS_DIR + Constants.SLASH, zipCreator, compress);
456b8a72a62Sopenharmony_ci                } else {
457b8a72a62Sopenharmony_ci                    pathToZipEntry(file.toPath(), file.getName() + Constants.SLASH, zipCreator, false);
458b8a72a62Sopenharmony_ci                }
459b8a72a62Sopenharmony_ci            }
460b8a72a62Sopenharmony_ci        }
461b8a72a62Sopenharmony_ci    }
462b8a72a62Sopenharmony_ci
463b8a72a62Sopenharmony_ci    private static void genBuildHash(Path path, ParallelScatterZipCreator zipCreator) {
464b8a72a62Sopenharmony_ci        String hash = hash(path);
465b8a72a62Sopenharmony_ci        if (hash.isEmpty()) {
466b8a72a62Sopenharmony_ci            return;
467b8a72a62Sopenharmony_ci        }
468b8a72a62Sopenharmony_ci        Path moduleJson = path.resolve(Constants.FILE_MODULE_JSON);
469b8a72a62Sopenharmony_ci        if (!Files.exists(moduleJson)) {
470b8a72a62Sopenharmony_ci            LOG.warning("module.json not found: " + path);
471b8a72a62Sopenharmony_ci            return;
472b8a72a62Sopenharmony_ci        }
473b8a72a62Sopenharmony_ci        try (FileInputStream input = new FileInputStream(moduleJson.toFile())) {
474b8a72a62Sopenharmony_ci            JSONObject jsonObject = JSON.parseObject(input, JSONObject.class);
475b8a72a62Sopenharmony_ci            if (jsonObject == null) {
476b8a72a62Sopenharmony_ci                LOG.warning("generateBuildHash: parse json is null.");
477b8a72a62Sopenharmony_ci                return;
478b8a72a62Sopenharmony_ci            }
479b8a72a62Sopenharmony_ci            JSONObject moduleObject = jsonObject.getJSONObject(Constants.MODULE);
480b8a72a62Sopenharmony_ci            if (moduleObject == null) {
481b8a72a62Sopenharmony_ci                LOG.warning("generateBuildHash: parse json[module] is null.");
482b8a72a62Sopenharmony_ci                return;
483b8a72a62Sopenharmony_ci            }
484b8a72a62Sopenharmony_ci            moduleObject.put(Constants.BUILD_HASH, hash);
485b8a72a62Sopenharmony_ci            byte[] data = JSON.toJSONBytes(jsonObject, SerializerFeature.WriteMapNullValue,
486b8a72a62Sopenharmony_ci                    SerializerFeature.WriteDateUseDateFormat, SerializerFeature.SortField);
487b8a72a62Sopenharmony_ci            ZipArchiveEntry zipEntry = new ZipArchiveEntry(Constants.FILE_MODULE_JSON);
488b8a72a62Sopenharmony_ci            zipEntry.setMethod(ZipArchiveEntry.STORED);
489b8a72a62Sopenharmony_ci            InputStreamSupplier supplier = () -> new ByteArrayInputStream(data);
490b8a72a62Sopenharmony_ci            zipCreator.addArchiveEntry(zipEntry, supplier);
491b8a72a62Sopenharmony_ci        } catch (IOException ex) {
492b8a72a62Sopenharmony_ci            LOG.warning("genBuildHash err: " + ex.getMessage());
493b8a72a62Sopenharmony_ci        }
494b8a72a62Sopenharmony_ci    }
495b8a72a62Sopenharmony_ci
496b8a72a62Sopenharmony_ci    private static void pathToZipEntry(Path path, String baseDir, ParallelScatterZipCreator zipCreator,
497b8a72a62Sopenharmony_ci                                       boolean compress) throws BundleException {
498b8a72a62Sopenharmony_ci        try {
499b8a72a62Sopenharmony_ci            File file = path.toFile();
500b8a72a62Sopenharmony_ci            if (file.isDirectory()) {
501b8a72a62Sopenharmony_ci                File[] files = file.listFiles();
502b8a72a62Sopenharmony_ci                if (files == null) {
503b8a72a62Sopenharmony_ci                    return;
504b8a72a62Sopenharmony_ci                }
505b8a72a62Sopenharmony_ci                for (File f : files) {
506b8a72a62Sopenharmony_ci                    addArchiveEntry(f, baseDir, zipCreator, compress);
507b8a72a62Sopenharmony_ci                }
508b8a72a62Sopenharmony_ci            } else {
509b8a72a62Sopenharmony_ci                addArchiveEntry(file, baseDir, zipCreator, compress);
510b8a72a62Sopenharmony_ci            }
511b8a72a62Sopenharmony_ci        } catch (IOException e) {
512b8a72a62Sopenharmony_ci            String errMsg = "pathToZip err: " + e.getMessage();
513b8a72a62Sopenharmony_ci            LOG.error(errMsg);
514b8a72a62Sopenharmony_ci            throw new BundleException(errMsg);
515b8a72a62Sopenharmony_ci        }
516b8a72a62Sopenharmony_ci    }
517b8a72a62Sopenharmony_ci
518b8a72a62Sopenharmony_ci    private static void addArchiveEntry(File file, String baseDir, ParallelScatterZipCreator zipCreator,
519b8a72a62Sopenharmony_ci                                        boolean compress)
520b8a72a62Sopenharmony_ci            throws IOException {
521b8a72a62Sopenharmony_ci        if (file.isDirectory()) {
522b8a72a62Sopenharmony_ci            File[] files = file.listFiles();
523b8a72a62Sopenharmony_ci            if (files == null) {
524b8a72a62Sopenharmony_ci                LOG.error("listFiles null: " + file.getName());
525b8a72a62Sopenharmony_ci                return;
526b8a72a62Sopenharmony_ci            }
527b8a72a62Sopenharmony_ci            if (files.length == 0) {
528b8a72a62Sopenharmony_ci                String entryName = (baseDir + file.getName() + File.separator)
529b8a72a62Sopenharmony_ci                        .replace(File.separator, Constants.SLASH);
530b8a72a62Sopenharmony_ci                ZipArchiveEntry zipEntry = new ZipArchiveEntry(entryName);
531b8a72a62Sopenharmony_ci                zipEntry.setMethod(ZipArchiveEntry.STORED);
532b8a72a62Sopenharmony_ci                zipEntry.setSize(0);
533b8a72a62Sopenharmony_ci                zipEntry.setCrc(0);
534b8a72a62Sopenharmony_ci                InputStreamSupplier supplier = () -> new ByteArrayInputStream(new byte[0]);
535b8a72a62Sopenharmony_ci                zipCreator.addArchiveEntry(zipEntry, supplier);
536b8a72a62Sopenharmony_ci            }
537b8a72a62Sopenharmony_ci            for (File f : files) {
538b8a72a62Sopenharmony_ci                addArchiveEntry(f, baseDir + file.getName() + File.separator, zipCreator, compress);
539b8a72a62Sopenharmony_ci            }
540b8a72a62Sopenharmony_ci        } else {
541b8a72a62Sopenharmony_ci            String entryName = (baseDir + file.getName()).replace(File.separator, Constants.SLASH);
542b8a72a62Sopenharmony_ci            ZipArchiveEntry zipEntry = new ZipArchiveEntry(entryName);
543b8a72a62Sopenharmony_ci            if (compress) {
544b8a72a62Sopenharmony_ci                zipEntry.setMethod(ZipArchiveEntry.DEFLATED);
545b8a72a62Sopenharmony_ci            } else {
546b8a72a62Sopenharmony_ci                zipEntry.setMethod(ZipArchiveEntry.STORED);
547b8a72a62Sopenharmony_ci            }
548b8a72a62Sopenharmony_ci            InputStreamSupplier supplier = () -> {
549b8a72a62Sopenharmony_ci                try {
550b8a72a62Sopenharmony_ci                    return getInputStream(entryName, file);
551b8a72a62Sopenharmony_ci                } catch (IOException e) {
552b8a72a62Sopenharmony_ci                    LOG.error("addArchiveEntry err: " + e.getMessage());
553b8a72a62Sopenharmony_ci                    return null;
554b8a72a62Sopenharmony_ci                }
555b8a72a62Sopenharmony_ci            };
556b8a72a62Sopenharmony_ci            zipCreator.addArchiveEntry(zipEntry, supplier);
557b8a72a62Sopenharmony_ci        }
558b8a72a62Sopenharmony_ci    }
559b8a72a62Sopenharmony_ci
560b8a72a62Sopenharmony_ci    private static InputStream getInputStream(String entryName, File file) throws IOException {
561b8a72a62Sopenharmony_ci        if (!entryName.contains(Constants.RAW_FILE_PATH) && !entryName.contains(Constants.RES_FILE_PATH) &&
562b8a72a62Sopenharmony_ci                file.getName().toLowerCase(Locale.ENGLISH).endsWith(Constants.JSON_SUFFIX)) {
563b8a72a62Sopenharmony_ci            try {
564b8a72a62Sopenharmony_ci                Object jsonObject = JSON.parse(Files.readAllBytes(file.toPath()));
565b8a72a62Sopenharmony_ci                byte[] data = JSON.toJSONBytes(jsonObject,
566b8a72a62Sopenharmony_ci                        SerializerFeature.WriteMapNullValue, SerializerFeature.WriteDateUseDateFormat);
567b8a72a62Sopenharmony_ci                return new ByteArrayInputStream(data);
568b8a72a62Sopenharmony_ci            } catch (JSONException ex) {
569b8a72a62Sopenharmony_ci                LOG.warning("json format err: " + file.getName());
570b8a72a62Sopenharmony_ci            }
571b8a72a62Sopenharmony_ci        }
572b8a72a62Sopenharmony_ci        return Files.newInputStream(file.toPath());
573b8a72a62Sopenharmony_ci    }
574b8a72a62Sopenharmony_ci
575b8a72a62Sopenharmony_ci    private static void filesToZipEntry(File[] files, ZipOutputStream zipOut, boolean genHash, boolean compress)
576b8a72a62Sopenharmony_ci            throws BundleException {
577b8a72a62Sopenharmony_ci        for (File file : files) {
578b8a72a62Sopenharmony_ci            if (file.isFile() && !file.getName().equals(Constants.FILE_PACK_INFO)) {
579b8a72a62Sopenharmony_ci                if (genHash && file.getName().equals(Constants.FILE_MODULE_JSON)) {
580b8a72a62Sopenharmony_ci                    continue;
581b8a72a62Sopenharmony_ci                }
582b8a72a62Sopenharmony_ci                pathToZipEntry(file.toPath(), Constants.NULL_DIR, zipOut, false);
583b8a72a62Sopenharmony_ci            } else if (file.isDirectory()) {
584b8a72a62Sopenharmony_ci                if (file.getName().equals(Constants.LIBS_DIR)) {
585b8a72a62Sopenharmony_ci                    pathToZipEntry(file.toPath(), Constants.LIBS_DIR + Constants.SLASH, zipOut, compress);
586b8a72a62Sopenharmony_ci                } else {
587b8a72a62Sopenharmony_ci                    pathToZipEntry(file.toPath(), file.getName() + Constants.SLASH, zipOut, false);
588b8a72a62Sopenharmony_ci                }
589b8a72a62Sopenharmony_ci            }
590b8a72a62Sopenharmony_ci        }
591b8a72a62Sopenharmony_ci    }
592b8a72a62Sopenharmony_ci
593b8a72a62Sopenharmony_ci    private static void genBuildHash(Path path, ZipOutputStream zipOut) {
594b8a72a62Sopenharmony_ci        String hash = hash(path);
595b8a72a62Sopenharmony_ci        if (hash.isEmpty()) {
596b8a72a62Sopenharmony_ci            return;
597b8a72a62Sopenharmony_ci        }
598b8a72a62Sopenharmony_ci        Path moduleJson = path.resolve(Constants.FILE_MODULE_JSON);
599b8a72a62Sopenharmony_ci        if (!Files.exists(moduleJson)) {
600b8a72a62Sopenharmony_ci            LOG.warning("module.json not found: " + path);
601b8a72a62Sopenharmony_ci            return;
602b8a72a62Sopenharmony_ci        }
603b8a72a62Sopenharmony_ci        try (FileInputStream input = new FileInputStream(moduleJson.toFile())) {
604b8a72a62Sopenharmony_ci            JSONObject jsonObject = JSON.parseObject(input, JSONObject.class);
605b8a72a62Sopenharmony_ci            if (jsonObject == null) {
606b8a72a62Sopenharmony_ci                LOG.warning("generateBuildHash: parse json is null.");
607b8a72a62Sopenharmony_ci                return;
608b8a72a62Sopenharmony_ci            }
609b8a72a62Sopenharmony_ci            JSONObject moduleObject = jsonObject.getJSONObject(Constants.MODULE);
610b8a72a62Sopenharmony_ci            if (moduleObject == null) {
611b8a72a62Sopenharmony_ci                LOG.warning("generateBuildHash: parse json[module] is null.");
612b8a72a62Sopenharmony_ci                return;
613b8a72a62Sopenharmony_ci            }
614b8a72a62Sopenharmony_ci            moduleObject.put(Constants.BUILD_HASH, hash);
615b8a72a62Sopenharmony_ci            byte[] data = JSON.toJSONBytes(jsonObject, SerializerFeature.WriteMapNullValue,
616b8a72a62Sopenharmony_ci                    SerializerFeature.WriteDateUseDateFormat, SerializerFeature.SortField);
617b8a72a62Sopenharmony_ci            CRC32 crc32 = new CRC32();
618b8a72a62Sopenharmony_ci            crc32.update(data, 0, data.length);
619b8a72a62Sopenharmony_ci            ZipEntry zipEntry = new ZipEntry(Constants.FILE_MODULE_JSON);
620b8a72a62Sopenharmony_ci            zipEntry.setMethod(ZipEntry.STORED);
621b8a72a62Sopenharmony_ci            zipEntry.setCompressedSize(data.length);
622b8a72a62Sopenharmony_ci            zipEntry.setCrc(crc32.getValue());
623b8a72a62Sopenharmony_ci            zipOut.putNextEntry(zipEntry);
624b8a72a62Sopenharmony_ci            try (InputStream inputStream = new ByteArrayInputStream(data)) {
625b8a72a62Sopenharmony_ci                IOUtils.copy(inputStream, zipOut, Constants.BUFFER_SIZE);
626b8a72a62Sopenharmony_ci            }
627b8a72a62Sopenharmony_ci            zipOut.closeEntry();
628b8a72a62Sopenharmony_ci        } catch (IOException ex) {
629b8a72a62Sopenharmony_ci            LOG.warning("genBuildHash err: " + ex.getMessage());
630b8a72a62Sopenharmony_ci        }
631b8a72a62Sopenharmony_ci    }
632b8a72a62Sopenharmony_ci
633b8a72a62Sopenharmony_ci    private static void pathToZipEntry(Path path, String baseDir, ZipOutputStream zipOut,
634b8a72a62Sopenharmony_ci                                       boolean compress) throws BundleException {
635b8a72a62Sopenharmony_ci        try {
636b8a72a62Sopenharmony_ci            File file = path.toFile();
637b8a72a62Sopenharmony_ci            if (file.isDirectory()) {
638b8a72a62Sopenharmony_ci                File[] files = file.listFiles();
639b8a72a62Sopenharmony_ci                if (files == null) {
640b8a72a62Sopenharmony_ci                    return;
641b8a72a62Sopenharmony_ci                }
642b8a72a62Sopenharmony_ci                for (File f : files) {
643b8a72a62Sopenharmony_ci                    addArchiveEntry(f, baseDir, zipOut, compress);
644b8a72a62Sopenharmony_ci                }
645b8a72a62Sopenharmony_ci            } else {
646b8a72a62Sopenharmony_ci                addArchiveEntry(file, baseDir, zipOut, compress);
647b8a72a62Sopenharmony_ci            }
648b8a72a62Sopenharmony_ci        } catch (IOException e) {
649b8a72a62Sopenharmony_ci            String errMsg = "pathToZip err: " + e.getMessage();
650b8a72a62Sopenharmony_ci            LOG.error(errMsg);
651b8a72a62Sopenharmony_ci            throw new BundleException(errMsg);
652b8a72a62Sopenharmony_ci        }
653b8a72a62Sopenharmony_ci    }
654b8a72a62Sopenharmony_ci
655b8a72a62Sopenharmony_ci    private static void addArchiveEntry(File file, String baseDir, ZipOutputStream zipOut, boolean compress)
656b8a72a62Sopenharmony_ci            throws IOException, BundleException {
657b8a72a62Sopenharmony_ci        if (file.isDirectory()) {
658b8a72a62Sopenharmony_ci            File[] files = file.listFiles();
659b8a72a62Sopenharmony_ci            if (files == null) {
660b8a72a62Sopenharmony_ci                LOG.error("listFiles null: " + file.getName());
661b8a72a62Sopenharmony_ci                return;
662b8a72a62Sopenharmony_ci            }
663b8a72a62Sopenharmony_ci            if (files.length == 0) {
664b8a72a62Sopenharmony_ci                String entryName = (baseDir + file.getName() + File.separator)
665b8a72a62Sopenharmony_ci                        .replace(File.separator, Constants.SLASH);
666b8a72a62Sopenharmony_ci                ZipEntry zipEntry = new ZipEntry(entryName);
667b8a72a62Sopenharmony_ci                zipEntry.setMethod(ZipEntry.STORED);
668b8a72a62Sopenharmony_ci                zipEntry.setSize(0);
669b8a72a62Sopenharmony_ci                zipEntry.setCrc(0);
670b8a72a62Sopenharmony_ci                zipOut.putNextEntry(zipEntry);
671b8a72a62Sopenharmony_ci                zipOut.closeEntry();
672b8a72a62Sopenharmony_ci            }
673b8a72a62Sopenharmony_ci            for (File f : files) {
674b8a72a62Sopenharmony_ci                addArchiveEntry(f, baseDir + file.getName() + File.separator, zipOut, compress);
675b8a72a62Sopenharmony_ci            }
676b8a72a62Sopenharmony_ci        } else {
677b8a72a62Sopenharmony_ci            String entryName = (baseDir + file.getName()).replace(File.separator, Constants.SLASH);
678b8a72a62Sopenharmony_ci            ZipEntry zipEntry = new ZipEntry(entryName);
679b8a72a62Sopenharmony_ci            if (compress) {
680b8a72a62Sopenharmony_ci                zipEntry.setMethod(ZipEntry.DEFLATED);
681b8a72a62Sopenharmony_ci            } else {
682b8a72a62Sopenharmony_ci                zipEntry.setMethod(ZipEntry.STORED);
683b8a72a62Sopenharmony_ci                CRC32 crc32 = PackageNormalize.getCrcFromFile(file);
684b8a72a62Sopenharmony_ci                zipEntry.setCrc(crc32.getValue());
685b8a72a62Sopenharmony_ci                zipEntry.setCompressedSize(file.length());
686b8a72a62Sopenharmony_ci            }
687b8a72a62Sopenharmony_ci            zipOut.putNextEntry(zipEntry);
688b8a72a62Sopenharmony_ci            try (InputStream input = Files.newInputStream(file.toPath())) {
689b8a72a62Sopenharmony_ci                IOUtils.copy(input, zipOut, Constants.BUFFER_SIZE);
690b8a72a62Sopenharmony_ci            }
691b8a72a62Sopenharmony_ci            zipOut.closeEntry();
692b8a72a62Sopenharmony_ci        }
693b8a72a62Sopenharmony_ci    }
694b8a72a62Sopenharmony_ci
695b8a72a62Sopenharmony_ci    private static boolean checkBundleTypeConsistency(List<String> hapPathList, List<String> hspPathList,
696b8a72a62Sopenharmony_ci                                                      Utility utility) {
697b8a72a62Sopenharmony_ci        String bundleType = "";
698b8a72a62Sopenharmony_ci        if (!hapPathList.isEmpty()) {
699b8a72a62Sopenharmony_ci            bundleType = getBundleTypeFromPath(Paths.get(hapPathList.get(0)));
700b8a72a62Sopenharmony_ci        } else if (!hspPathList.isEmpty()) {
701b8a72a62Sopenharmony_ci            bundleType = getBundleTypeFromPath(Paths.get(hspPathList.get(0)));
702b8a72a62Sopenharmony_ci        }
703b8a72a62Sopenharmony_ci        if (bundleType == null || bundleType.isEmpty()) {
704b8a72a62Sopenharmony_ci            return false;
705b8a72a62Sopenharmony_ci        }
706b8a72a62Sopenharmony_ci        for (String hapPath : hapPathList) {
707b8a72a62Sopenharmony_ci            if (!bundleType.equals(getBundleTypeFromPath(Paths.get(hapPath)))) {
708b8a72a62Sopenharmony_ci                LOG.error("bundleType is not same");
709b8a72a62Sopenharmony_ci                return false;
710b8a72a62Sopenharmony_ci            }
711b8a72a62Sopenharmony_ci        }
712b8a72a62Sopenharmony_ci        for (String hspPath : hspPathList) {
713b8a72a62Sopenharmony_ci            if (!bundleType.equals(getBundleTypeFromPath(Paths.get(hspPath)))) {
714b8a72a62Sopenharmony_ci                LOG.error("bundleType is not same");
715b8a72a62Sopenharmony_ci                return false;
716b8a72a62Sopenharmony_ci            }
717b8a72a62Sopenharmony_ci        }
718b8a72a62Sopenharmony_ci        if (bundleType.equals(Constants.BUNDLE_TYPE_SHARED)) {
719b8a72a62Sopenharmony_ci            utility.setIsSharedApp(true);
720b8a72a62Sopenharmony_ci        }
721b8a72a62Sopenharmony_ci        return true;
722b8a72a62Sopenharmony_ci    }
723b8a72a62Sopenharmony_ci
724b8a72a62Sopenharmony_ci    private static boolean moduleJsonAndPackInfoExists(List<String> hapPathList, List<String> hspPathList) {
725b8a72a62Sopenharmony_ci        for (String hapPath : hapPathList) {
726b8a72a62Sopenharmony_ci            Path path = Paths.get(hapPath);
727b8a72a62Sopenharmony_ci            if (!Files.exists(path.resolve(Constants.FILE_MODULE_JSON))) {
728b8a72a62Sopenharmony_ci                LOG.error("not found module.json in path: " + path);
729b8a72a62Sopenharmony_ci                return false;
730b8a72a62Sopenharmony_ci            }
731b8a72a62Sopenharmony_ci            if (!Files.exists(path.resolve(Constants.FILE_PACK_INFO))) {
732b8a72a62Sopenharmony_ci                LOG.error("not found pack.info in path: " + path);
733b8a72a62Sopenharmony_ci                return false;
734b8a72a62Sopenharmony_ci            }
735b8a72a62Sopenharmony_ci        }
736b8a72a62Sopenharmony_ci        for (String hspPath : hspPathList) {
737b8a72a62Sopenharmony_ci            Path path = Paths.get(hspPath);
738b8a72a62Sopenharmony_ci            if (Files.isDirectory(path)) {
739b8a72a62Sopenharmony_ci                if (!Files.exists(path.resolve(Constants.FILE_MODULE_JSON))) {
740b8a72a62Sopenharmony_ci                    LOG.error("not found module.json in path: " + path);
741b8a72a62Sopenharmony_ci                    return false;
742b8a72a62Sopenharmony_ci                }
743b8a72a62Sopenharmony_ci                if (!Files.exists(path.resolve(Constants.FILE_PACK_INFO))) {
744b8a72a62Sopenharmony_ci                    LOG.error("not found pack.info in path: " + path);
745b8a72a62Sopenharmony_ci                    return false;
746b8a72a62Sopenharmony_ci                }
747b8a72a62Sopenharmony_ci            }
748b8a72a62Sopenharmony_ci        }
749b8a72a62Sopenharmony_ci        return true;
750b8a72a62Sopenharmony_ci    }
751b8a72a62Sopenharmony_ci
752b8a72a62Sopenharmony_ci    private static boolean isFileValid(String filePath, String suffix) {
753b8a72a62Sopenharmony_ci        Path path = Paths.get(filePath);
754b8a72a62Sopenharmony_ci        return Files.isRegularFile(path) && path.getFileName().toString().endsWith(suffix);
755b8a72a62Sopenharmony_ci    }
756b8a72a62Sopenharmony_ci
757b8a72a62Sopenharmony_ci    private static boolean isDirValid(String filePath) {
758b8a72a62Sopenharmony_ci        return Files.isDirectory(Paths.get(filePath));
759b8a72a62Sopenharmony_ci    }
760b8a72a62Sopenharmony_ci
761b8a72a62Sopenharmony_ci    /**
762b8a72a62Sopenharmony_ci     * verify input param
763b8a72a62Sopenharmony_ci     *
764b8a72a62Sopenharmony_ci     * @param utility common data
765b8a72a62Sopenharmony_ci     * @return true if verify ok
766b8a72a62Sopenharmony_ci     */
767b8a72a62Sopenharmony_ci    public static boolean isVerifyValidInFastAppMode(Utility utility) {
768b8a72a62Sopenharmony_ci        if (!isVerifyValid(utility)) {
769b8a72a62Sopenharmony_ci            return false;
770b8a72a62Sopenharmony_ci        }
771b8a72a62Sopenharmony_ci        if (!utility.getHapPath().isEmpty() &&
772b8a72a62Sopenharmony_ci                (!isFormatPathValid(utility.getHapPath(), utility.getFormattedHapPathList()) ||
773b8a72a62Sopenharmony_ci                        !isHapPathValid(utility.getFormattedHapPathList()))) {
774b8a72a62Sopenharmony_ci            LOG.error("CompressVerify::isVerifyValidInFastAppMode hap-path is invalid.");
775b8a72a62Sopenharmony_ci            return false;
776b8a72a62Sopenharmony_ci        }
777b8a72a62Sopenharmony_ci        if (!utility.getHspPath().isEmpty() &&
778b8a72a62Sopenharmony_ci                (!isFormatPathValid(utility.getHspPath(), utility.getFormattedHspPathList()) ||
779b8a72a62Sopenharmony_ci                        !isHspPathValid(utility.getFormattedHspPathList()))) {
780b8a72a62Sopenharmony_ci            LOG.error("CompressVerify::isVerifyValidInFastAppMode hsp-path is invalid.");
781b8a72a62Sopenharmony_ci            return false;
782b8a72a62Sopenharmony_ci        }
783b8a72a62Sopenharmony_ci        if (utility.getHapPath().isEmpty() && utility.getHspPath().isEmpty()) {
784b8a72a62Sopenharmony_ci            LOG.error("CompressVerify::isVerifyValidInFastAppMode hap-path and hsp-path is empty.");
785b8a72a62Sopenharmony_ci            return false;
786b8a72a62Sopenharmony_ci        }
787b8a72a62Sopenharmony_ci        if (!moduleJsonAndPackInfoExists(utility.getFormattedHapPathList(), utility.getFormattedHspPathList())) {
788b8a72a62Sopenharmony_ci            LOG.error("CompressVerify::isVerifyValidInFastAppMode hap-path or hsp-path is invalid.");
789b8a72a62Sopenharmony_ci            return false;
790b8a72a62Sopenharmony_ci        }
791b8a72a62Sopenharmony_ci        if (!checkBundleTypeConsistency(
792b8a72a62Sopenharmony_ci                utility.getFormattedHapPathList(), utility.getFormattedHspPathList(), utility)) {
793b8a72a62Sopenharmony_ci            LOG.error("CompressVerify::isVerifyValidInFastAppMode bundleType is inconsistent.");
794b8a72a62Sopenharmony_ci            return false;
795b8a72a62Sopenharmony_ci        }
796b8a72a62Sopenharmony_ci        if (!isPackInfoValid(Paths.get(utility.getPackInfoPath()),
797b8a72a62Sopenharmony_ci                utility.getFormattedHapPathList(), utility.getFormattedHspPathList())) {
798b8a72a62Sopenharmony_ci            LOG.error("CompressVerify::isVerifyValidInFastAppMode pack.info is invalid.");
799b8a72a62Sopenharmony_ci            return false;
800b8a72a62Sopenharmony_ci        }
801b8a72a62Sopenharmony_ci        if (!utility.getEncryptPath().isEmpty()
802b8a72a62Sopenharmony_ci                && !isFileValid(utility.getEncryptPath(), Constants.FILE_ENCRYPT_JSON)) {
803b8a72a62Sopenharmony_ci            LOG.error("CompressVerify::isVerifyValidInFastAppMode encrypt-path is invalid.");
804b8a72a62Sopenharmony_ci            return false;
805b8a72a62Sopenharmony_ci        }
806b8a72a62Sopenharmony_ci        Path outPath = Paths.get(utility.getOutPath());
807b8a72a62Sopenharmony_ci        if (utility.getForceRewrite().equals(Constants.FALSE) && Files.exists(outPath)) {
808b8a72a62Sopenharmony_ci            LOG.error("CompressVerify::isVerifyValidInFastAppMode out file already existed.");
809b8a72a62Sopenharmony_ci            return false;
810b8a72a62Sopenharmony_ci        }
811b8a72a62Sopenharmony_ci        if (!outPath.getFileName().toString().endsWith(Constants.APP_SUFFIX)) {
812b8a72a62Sopenharmony_ci            LOG.error("CompressVerify::isVerifyValidInFastAppMode out-path must end with .app.");
813b8a72a62Sopenharmony_ci            return false;
814b8a72a62Sopenharmony_ci        }
815b8a72a62Sopenharmony_ci        return true;
816b8a72a62Sopenharmony_ci    }
817b8a72a62Sopenharmony_ci
818b8a72a62Sopenharmony_ci    private static boolean isVerifyValid(Utility utility) {
819b8a72a62Sopenharmony_ci        if (utility.getPackInfoPath().isEmpty()) {
820b8a72a62Sopenharmony_ci            LOG.error("CompressVerify::isArgsValidInAppMode pack-info-path is empty.");
821b8a72a62Sopenharmony_ci            return false;
822b8a72a62Sopenharmony_ci        }
823b8a72a62Sopenharmony_ci        if (!isFileValid(utility.getPackInfoPath(), Constants.FILE_PACK_INFO)) {
824b8a72a62Sopenharmony_ci            LOG.error("CompressVerify::isVerifyValidInFastAppMode pack-info-path is invalid.");
825b8a72a62Sopenharmony_ci            return false;
826b8a72a62Sopenharmony_ci        }
827b8a72a62Sopenharmony_ci        if (!utility.getSignaturePath().isEmpty() && !isFileValid(utility.getSignaturePath(), "")) {
828b8a72a62Sopenharmony_ci            LOG.error("CompressVerify::isVerifyValidInFastAppMode signature-path is invalid.");
829b8a72a62Sopenharmony_ci            return false;
830b8a72a62Sopenharmony_ci        }
831b8a72a62Sopenharmony_ci        if (!utility.getCertificatePath().isEmpty() &&
832b8a72a62Sopenharmony_ci                !isFileValid(utility.getCertificatePath(), "")) {
833b8a72a62Sopenharmony_ci            LOG.error("CompressVerify::isVerifyValidInFastAppMode certificate-path is invalid.");
834b8a72a62Sopenharmony_ci            return false;
835b8a72a62Sopenharmony_ci        }
836b8a72a62Sopenharmony_ci        if (!utility.getPackResPath().isEmpty() && !isFileValid(utility.getPackResPath(), Constants.FILE_PACK_RES)) {
837b8a72a62Sopenharmony_ci            LOG.error("CompressVerify::isVerifyValidInFastAppMode pack-res-path is invalid.");
838b8a72a62Sopenharmony_ci            return false;
839b8a72a62Sopenharmony_ci        }
840b8a72a62Sopenharmony_ci        if (!utility.getEntryCardPath().isEmpty() &&
841b8a72a62Sopenharmony_ci                !CompressVerify.compatibleProcess(utility, utility.getEntryCardPath(),
842b8a72a62Sopenharmony_ci                        utility.getformattedEntryCardPathList(), Constants.PNG_SUFFIX)) {
843b8a72a62Sopenharmony_ci            LOG.error("CompressVerify::isVerifyValidInFastAppMode entrycard-path is invalid.");
844b8a72a62Sopenharmony_ci            return false;
845b8a72a62Sopenharmony_ci        }
846b8a72a62Sopenharmony_ci        if (utility.getOutPath().isEmpty()) {
847b8a72a62Sopenharmony_ci            LOG.error("CompressVerify::isVerifyValidInFastAppMode out-path is empty.");
848b8a72a62Sopenharmony_ci            return false;
849b8a72a62Sopenharmony_ci        }
850b8a72a62Sopenharmony_ci        return true;
851b8a72a62Sopenharmony_ci    }
852b8a72a62Sopenharmony_ci
853b8a72a62Sopenharmony_ci    private static boolean isHapPathValid(List<String> formatPathList) {
854b8a72a62Sopenharmony_ci        for (String path : formatPathList) {
855b8a72a62Sopenharmony_ci            if (!isDirValid(path)) {
856b8a72a62Sopenharmony_ci                return false;
857b8a72a62Sopenharmony_ci            }
858b8a72a62Sopenharmony_ci        }
859b8a72a62Sopenharmony_ci        return true;
860b8a72a62Sopenharmony_ci    }
861b8a72a62Sopenharmony_ci
862b8a72a62Sopenharmony_ci    private static boolean isHspPathValid(List<String> formatPathList) {
863b8a72a62Sopenharmony_ci        for (String path : formatPathList) {
864b8a72a62Sopenharmony_ci            if (!isDirValid(path) && !isFileValid(path, Constants.HSP_SUFFIX)) {
865b8a72a62Sopenharmony_ci                return false;
866b8a72a62Sopenharmony_ci            }
867b8a72a62Sopenharmony_ci        }
868b8a72a62Sopenharmony_ci        return true;
869b8a72a62Sopenharmony_ci    }
870b8a72a62Sopenharmony_ci
871b8a72a62Sopenharmony_ci    private static boolean isFormatPathValid(String inputPath, List<String> formatPathList) {
872b8a72a62Sopenharmony_ci        Set<String> formatPathSet = new HashSet<>();
873b8a72a62Sopenharmony_ci        for (String path : inputPath.split(Constants.COMMA)) {
874b8a72a62Sopenharmony_ci            try {
875b8a72a62Sopenharmony_ci                Path realpath = Paths.get(path).toRealPath();
876b8a72a62Sopenharmony_ci                if (Files.exists(realpath)) {
877b8a72a62Sopenharmony_ci                    formatPathSet.add(realpath.toString());
878b8a72a62Sopenharmony_ci                } else {
879b8a72a62Sopenharmony_ci                    LOG.error("PackageUtil::formatPath not exists: " + realpath);
880b8a72a62Sopenharmony_ci                    return false;
881b8a72a62Sopenharmony_ci                }
882b8a72a62Sopenharmony_ci            } catch (IOException ex) {
883b8a72a62Sopenharmony_ci                LOG.error("PackageUtil::formatPath err: " + ex.getMessage());
884b8a72a62Sopenharmony_ci                return false;
885b8a72a62Sopenharmony_ci            }
886b8a72a62Sopenharmony_ci        }
887b8a72a62Sopenharmony_ci        formatPathList.addAll(formatPathSet);
888b8a72a62Sopenharmony_ci        return true;
889b8a72a62Sopenharmony_ci    }
890b8a72a62Sopenharmony_ci
891b8a72a62Sopenharmony_ci    private static boolean isPackInfoValid(Path packInfo, List<String> hapPathList, List<String> hspPathList) {
892b8a72a62Sopenharmony_ci        List<String> allPackages = getPackageNameFromPath(packInfo);
893b8a72a62Sopenharmony_ci        Set<String> allPackageSet = new HashSet<>(allPackages);
894b8a72a62Sopenharmony_ci        if (allPackages.size() > allPackageSet.size()) {
895b8a72a62Sopenharmony_ci            LOG.error("package name is redundant in app pack.info: " + packInfo);
896b8a72a62Sopenharmony_ci            return false;
897b8a72a62Sopenharmony_ci        }
898b8a72a62Sopenharmony_ci        if (allPackages.isEmpty()) {
899b8a72a62Sopenharmony_ci            LOG.error("app pack.info format err: " + packInfo);
900b8a72a62Sopenharmony_ci            return false;
901b8a72a62Sopenharmony_ci        }
902b8a72a62Sopenharmony_ci        Set<String> packages = new HashSet<>();
903b8a72a62Sopenharmony_ci        for (String hapPath : hapPathList) {
904b8a72a62Sopenharmony_ci            List<String> list = getPackageNameFromPath(Paths.get(hapPath));
905b8a72a62Sopenharmony_ci            if (list.size() != 1) {
906b8a72a62Sopenharmony_ci                LOG.error("module pack.info format err: " + hapPath);
907b8a72a62Sopenharmony_ci                return false;
908b8a72a62Sopenharmony_ci            }
909b8a72a62Sopenharmony_ci            String packageName = list.get(0);
910b8a72a62Sopenharmony_ci            if (!allPackages.contains(packageName)) {
911b8a72a62Sopenharmony_ci                LOG.error("module pack.info name not exist in app pack.info name list: " + hapPath);
912b8a72a62Sopenharmony_ci                return false;
913b8a72a62Sopenharmony_ci            }
914b8a72a62Sopenharmony_ci            if (packages.contains(packageName)) {
915b8a72a62Sopenharmony_ci                LOG.error("package name is redundant in " + hapPath);
916b8a72a62Sopenharmony_ci                return false;
917b8a72a62Sopenharmony_ci            }
918b8a72a62Sopenharmony_ci            packages.add(packageName);
919b8a72a62Sopenharmony_ci        }
920b8a72a62Sopenharmony_ci        for (String hspPath : hspPathList) {
921b8a72a62Sopenharmony_ci            List<String> list = getPackageNameFromPath(Paths.get(hspPath));
922b8a72a62Sopenharmony_ci            if (list.size() != 1) {
923b8a72a62Sopenharmony_ci                LOG.error("module pack.info format err: " + hspPath);
924b8a72a62Sopenharmony_ci                return false;
925b8a72a62Sopenharmony_ci            }
926b8a72a62Sopenharmony_ci            String packageName = list.get(0);
927b8a72a62Sopenharmony_ci            if (!allPackages.contains(packageName)) {
928b8a72a62Sopenharmony_ci                LOG.error("module pack.info name not exist in app pack.info name list: " + hspPath);
929b8a72a62Sopenharmony_ci                return false;
930b8a72a62Sopenharmony_ci            }
931b8a72a62Sopenharmony_ci            if (packages.contains(packageName)) {
932b8a72a62Sopenharmony_ci                LOG.error("package name is redundant in " + hspPath);
933b8a72a62Sopenharmony_ci                return false;
934b8a72a62Sopenharmony_ci            }
935b8a72a62Sopenharmony_ci            packages.add(packageName);
936b8a72a62Sopenharmony_ci        }
937b8a72a62Sopenharmony_ci        if (!allPackageSet.equals(packages)) {
938b8a72a62Sopenharmony_ci            LOG.error("package name not same between module and app pack.info.");
939b8a72a62Sopenharmony_ci            return false;
940b8a72a62Sopenharmony_ci        }
941b8a72a62Sopenharmony_ci        return true;
942b8a72a62Sopenharmony_ci    }
943b8a72a62Sopenharmony_ci
944b8a72a62Sopenharmony_ci}
945