• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 
16 package ohos;
17 
18 import java.io.BufferedInputStream;
19 import java.io.BufferedReader;
20 import java.io.ByteArrayOutputStream;
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.FileNotFoundException;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28 
29 import java.nio.charset.StandardCharsets;
30 import java.nio.file.attribute.FileTime;
31 
32 import java.util.ArrayList;
33 import java.util.Enumeration;
34 import java.util.HashMap;
35 import java.util.List;
36 import java.util.Locale;
37 import java.util.stream.Collectors;
38 import java.util.zip.CRC32;
39 import java.util.zip.CheckedOutputStream;
40 import java.util.zip.ZipEntry;
41 import java.util.zip.ZipFile;
42 import java.util.zip.ZipInputStream;
43 import java.util.zip.ZipOutputStream;
44 
45 
46 /**
47  * bundle uncompress.
48  *
49  */
50 public class Uncompress {
51     private static final String HAP_SUFFIX = ".hap";
52     private static final String APK_SUFFIX = ".apk";
53     private static final String JSON_SUFFIX = ".json";
54     private static final String HSP_SUFFIX = ".hsp";
55 
56     private static final String PACK_INFO = "pack.info";
57     private static final String HARMONY_PROFILE = "config.json";
58     private static final String MODULE_JSON = "module.json";
59     private static final String RESOURCE_INDEX = "resources.index";
60     private static final String RPCID_SC = "rpcid.sc";
61     private static final String LINUX_FILE_SEPARATOR = "/";
62     private static final String TEMP_PATH = "temp";
63     private static final String HAP_SUFFIXI = ".hap";
64     private static final String ENTRY_TYPE = "entry";
65     private static final String SYSTEM_ACTION = "action.system.home";
66     private static final String SYSTEM_WANT_HOME = "ohos.want.action.home";
67     private static final String SYSTEM_ENTITY = "entity.system.home";
68     private static final int READ_BUFFER_SIZE = 1024;
69     private static final int BUFFER_SIZE = 10 * 1024;
70     private static final long FILE_TIME = 1546272000000L;
71     private static final String LIBS_DIR_NAME = "libs";
72     private static final String CUT_ENTRY_FILENAME = "cut_entry.apk";
73     private static final String SO_SUFFIX = ".so";
74     private static final String RESOURCE_PATH = "resources/base/profile/";
75     private static final String TRUE = "true";
76     private static final String HQF_SUFFIX = ".hqf";
77     private static final String PATCH_JSON = "patch.json";
78     private static final String HAP_PREFIX = "HAP";
79     private static final Log LOG = new Log(Uncompress.class.toString());
80 
81     /**
82      * unpackage entrance.
83      *
84      * @param utility common data
85      * @return unpackageProcess if unpackage succeed
86      */
unpackageProcess(Utility utility)87     static boolean unpackageProcess(Utility utility) {
88         if (utility == null) {
89             LOG.error("Uncompress::unpackageProcess utility is null.");
90             return false;
91         }
92         boolean unpackageResult = true;
93         File destFile = new File(utility.getOutPath());
94 
95         if (!destFile.exists()) {
96             if (!destFile.mkdirs()) {
97                 LOG.error("Uncompress::unpackageProcess create out file directory failed!");
98                 return false;
99             }
100         }
101         try {
102             if (!Utility.MODE_HAP.equals(utility.getMode()) || !TRUE.equals(utility.getRpcid())) {
103                 if (!utility.getForceRewrite().isEmpty() && "true".equals(utility.getForceRewrite())) {
104                     File outPath = new File(utility.getOutPath());
105                     deleteFile(outPath);
106                     outPath.mkdirs();
107                 }
108             }
109             switch (utility.getMode()) {
110                 case Utility.MODE_HAP:
111                     unpackageHapMode(utility);
112                     break;
113                 case Utility.MODE_HAR:
114                     dataTransferAllFiles(utility.getHarPath(), utility.getOutPath());
115                     break;
116                 case Utility.MODE_APP:
117                     dataTransferFilesByApp(utility, utility.getAppPath(), utility.getOutPath());
118                     break;
119                 case Utility.MODE_APPQF:
120                     uncompressAPPQFFile(utility);
121                     break;
122                 case Utility.MODE_HSP:
123                     dataTransferAllFiles(utility.getHspPath(), utility.getOutPath());
124                     break;
125                 default:
126                     LOG.error("Uncompress::unpackageProcess input wrong type!");
127                     throw new BundleException("Uncompress::unpackageProcess input wrong type!");
128             }
129         } catch (BundleException ignored) {
130             unpackageResult = false;
131             LOG.error("Uncompress::unpackageProcess Bundle exception");
132         }
133         // return uncompress information.
134         if (!unpackageResult) {
135             LOG.error("Uncompress::unpackageProcess unpackage failed!");
136         }
137         return unpackageResult;
138     }
139 
140     /**
141      * unpack hap.
142      *
143      * @param utility common data
144      */
unpackageHapMode(Utility utility)145     static void unpackageHapMode(Utility utility) throws BundleException {
146         if (!Utility.MODE_HAP.equals(utility.getMode())) {
147             throw new BundleException("Uncompress::unpackageHapMode input wrong unpack mode");
148         }
149         try {
150             if (TRUE.equals(utility.getRpcid())) {
151                 getRpcidFromHap(utility.getHapPath(), utility.getOutPath());
152                 return;
153             }
154             if (TRUE.equals(utility.getUnpackApk())) {
155                 unzip(utility, utility.getHapPath(), utility.getOutPath(), APK_SUFFIX);
156                 String[] temp = utility.getHapPath().replace("\\", "/").split("/");
157                 String hapName = temp[temp.length - 1];
158                 repackHap(utility.getHapPath(), utility.getOutPath(), hapName, utility.getUnpackApk());
159             } else {
160                 dataTransferAllFiles(utility.getHapPath(), utility.getOutPath());
161             }
162         } catch (BundleException e) {
163             LOG.error("Uncompress::unpackageHapMode failed");
164             throw new BundleException("Uncompress::unpackageHapMode failed");
165         }
166     }
167 
168     /**
169      * uncompress app.
170      *
171      * @param utility common data
172      * @return the uncompress result
173      */
uncompressAppByPath(Utility utility)174     static UncompressResult uncompressAppByPath(Utility utility) {
175         UncompressResult compressResult = new UncompressResult();
176         InputStream input = null;
177         String srcPath = utility.getAppPath();
178         String parseMode = utility.getParseMode();
179 
180         try {
181             if (UncompressEntrance.PARSE_MODE_HAPLIST.equals(parseMode)) {
182                 compressResult = uncompress(utility.getDeviceType(), srcPath, PACK_INFO);
183             } else if (UncompressEntrance.PARSE_MODE_HAPINFO.equals(parseMode)) {
184                 compressResult = uncompressHapAndHspFromAppPath(srcPath, utility);
185             } else if (UncompressEntrance.PARSE_MODE_ALL.equals(parseMode)) {
186                 compressResult = uncompressAllAppByPath(srcPath);
187             } else {
188                 LOG.error("Uncompress::uncompressApp parseMode is invalid!");
189                 compressResult.setResult(false);
190                 compressResult.setMessage("ParseApp parseMode is invalid");
191             }
192         } catch (BundleException e) {
193             LOG.error("Uncompress::uncompressApp Bundle exception");
194             compressResult.setResult(false);
195             compressResult.setMessage("ParseApp Bundle exception");
196         } finally {
197             Utility.closeStream(input);
198         }
199         return compressResult;
200     }
201 
uncompressHapAndHspFromAppPath( String srcPath, Utility utility)202     private static UncompressResult uncompressHapAndHspFromAppPath(
203             String srcPath, Utility utility) throws BundleException {
204         UncompressResult result = new UncompressResult();
205         String hapName = utility.getHapName();
206         if (!hapName.toLowerCase(Locale.ENGLISH).endsWith(HAP_SUFFIX)
207                 && !hapName.toLowerCase(Locale.ENGLISH).endsWith(HSP_SUFFIX)) {
208             hapName += HAP_SUFFIX;
209         }
210         ZipFile appFile = null;
211         ZipEntry entry = null;
212         InputStream stream = null;
213         try {
214             appFile = new ZipFile(srcPath);
215             Enumeration<? extends ZipEntry> entries = appFile.entries();
216             while (entries.hasMoreElements()) {
217                 entry = entries.nextElement();
218                 stream = appFile.getInputStream(entry);
219                 if (!hapName.equals(entry.getName().toLowerCase(Locale.ENGLISH))) {
220                     continue;
221                 }
222                 UncompressResult hapInfo = uncompressHapByStream("", stream, hapName);
223                 if (hapInfo.getProfileInfos() != null && hapInfo.getProfileInfos().size() > 0) {
224                     result.addProfileInfo(hapInfo.getProfileInfos().get(0));
225                     result.addProfileInfoStr(hapInfo.getProfileInfosStr().get(0));
226                 }
227                 break;
228             }
229         } catch (IOException | BundleException e) {
230             LOG.error("uncompressHapFromAppPath failed!");
231             throw new BundleException("uncompressHapFromAppPath failed!");
232         } finally {
233             Utility.closeStream(appFile);
234             Utility.closeStream(stream);
235         }
236         return result;
237     }
238 
uncompressAllAppByPath(String srcPath)239     private static UncompressResult uncompressAllAppByPath(String srcPath) throws BundleException {
240         UncompressResult result = new UncompressResult();
241         ZipFile appFile = null;
242         ZipEntry entry = null;
243         InputStream stream = null;
244         try {
245             appFile = new ZipFile(srcPath);
246             Enumeration<? extends ZipEntry> entries = appFile.entries();
247             while (entries.hasMoreElements()) {
248                 entry = entries.nextElement();
249                 stream = appFile.getInputStream(entry);
250                 if (PACK_INFO.equals(entry.getName().toLowerCase(Locale.ENGLISH))) {
251                     String packInfo = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))
252                             .lines().parallel().collect(Collectors.joining(System.lineSeparator()));
253                     List<PackInfo> packInfos = JsonUtil.parseHapList("", packInfo);
254                     result.setPackInfoStr(packInfo);
255                     result.setPackInfos(packInfos);
256                 }
257                 if (entry.getName().toLowerCase(Locale.ENGLISH).endsWith(HAP_SUFFIX)
258                         || entry.getName().toLowerCase(Locale.ENGLISH).endsWith(HSP_SUFFIX)) {
259                     UncompressResult hapInfo = uncompressHapByStream("", stream, entry.getName());
260                     if (hapInfo.getProfileInfos() != null && hapInfo.getProfileInfos().size() > 0) {
261                         result.addProfileInfo(hapInfo.getProfileInfos().get(0));
262                         result.addProfileInfoStr(hapInfo.getProfileInfosStr().get(0));
263                     }
264                 }
265             }
266             result = checkParseAllResult(result);
267             result = obtainLabelAndIcon(result);
268         } catch (IOException | BundleException e) {
269             LOG.error("uncompressAllAppByPath failed!");
270             throw new BundleException("uncompressAllAppByPath failed!");
271         } finally {
272             Utility.closeStream(appFile);
273             Utility.closeStream(stream);
274         }
275         return result;
276     }
277 
278 
279     /**
280      * uncompress app.
281      *
282      * @param utility common data
283      * @param input the InputStream about the app package.
284      * @return the uncompress result
285      */
uncompressAppByInput(Utility utility, InputStream input)286     static UncompressResult uncompressAppByInput(Utility utility, InputStream input) {
287         UncompressResult compressResult = new UncompressResult();
288         String parseMode = utility.getParseMode();
289         try {
290             if (!parseMode.isEmpty() && UncompressEntrance.PARSE_MODE_HAPLIST.equals(parseMode)) {
291                 compressResult = uncompressByInput(utility.getDeviceType(), input, PACK_INFO, "");
292             } else if (!parseMode.isEmpty() && UncompressEntrance.PARSE_MODE_HAPINFO.equals(parseMode)) {
293                 compressResult = uncompressHapFromAppStream(utility.getDeviceType(), input, utility.getHapName());
294             } else if (!parseMode.isEmpty() && UncompressEntrance.PARSE_MODE_ALL.equals(parseMode)) {
295                 compressResult = uncompressAllFromAppStream(input);
296             } else {
297                 LOG.error("Uncompress::uncompressAppByInput parseMode is invalid!");
298                 compressResult.setResult(false);
299                 compressResult.setMessage("ParseApp parseMode is invalid");
300             }
301         } catch (BundleException exception) {
302             LOG.error("Uncompress::uncompressAppByInput Bundle exception");
303             compressResult.setResult(false);
304             compressResult.setMessage("ParseApp Bundle exception");
305         }
306         return compressResult;
307     }
308 
uncompressHapFromAppStream(String deviceType, InputStream stream, String fileName)309     private static UncompressResult uncompressHapFromAppStream(String deviceType, InputStream stream, String fileName)
310             throws BundleException {
311         String hapFile = fileName;
312         if (!fileName.toLowerCase(Locale.ENGLISH).endsWith(HAP_SUFFIX)
313                 && !fileName.toLowerCase(Locale.ENGLISH).endsWith(HSP_SUFFIX)) {
314             hapFile += HAP_SUFFIX;
315         }
316         UncompressResult result = new UncompressResult();
317         ZipInputStream zipInputStream = null;
318         try {
319             zipInputStream = new ZipInputStream(stream);
320             ZipEntry appEntry;
321             while ((appEntry = zipInputStream.getNextEntry()) != null) {
322                 if (appEntry.getName().toLowerCase(Locale.ENGLISH).equals(hapFile)) {
323                     result = uncompressHapByStream("", zipInputStream, appEntry.getName());
324                 }
325             }
326         } catch (IOException e) {
327             LOG.error("uncompressHapFromAppStream failed!");
328             throw new BundleException("uncompressHapFromAppStream failed!");
329         } finally {
330             Utility.closeStream(zipInputStream);
331         }
332         return result;
333     }
334 
uncompressAllFromAppStream(InputStream stream)335     private static UncompressResult uncompressAllFromAppStream(InputStream stream) throws BundleException {
336         UncompressResult result = new UncompressResult();
337         ZipInputStream zipInputStream = null;
338         ByteArrayOutputStream outputStream = null;
339         try {
340             zipInputStream = new ZipInputStream(stream);
341             ZipEntry entry;
342             while ((entry = zipInputStream.getNextEntry()) != null) {
343                 if (PACK_INFO.equals(entry.getName().toLowerCase(Locale.ENGLISH))) {
344                     String packInfo = new BufferedReader(new InputStreamReader(zipInputStream,
345                             StandardCharsets.UTF_8)).lines().parallel()
346                             .collect(Collectors.joining(System.lineSeparator()));
347                     List<PackInfo> packInfos = JsonUtil.parseHapList("", packInfo);
348                     result.setPackInfoStr(packInfo);
349                     result.setPackInfos(packInfos);
350                 }
351                 if (entry.getName().toLowerCase(Locale.ENGLISH).endsWith(HAP_SUFFIX)
352                         || entry.getName().toLowerCase(Locale.ENGLISH).endsWith(HSP_SUFFIX)) {
353                     UncompressResult hapResult = uncompressHapByStream("", zipInputStream, entry.getName());
354                     if (hapResult.getProfileInfos() != null && hapResult.getProfileInfos().size() > 0) {
355                         result.addProfileInfo(hapResult.getProfileInfos().get(0));
356                         result.addProfileInfoStr(hapResult.getProfileInfosStr().get(0));
357                     }
358                 }
359             }
360             result = checkParseAllResult(result);
361             result = obtainLabelAndIcon(result);
362         } catch (IOException | BundleException e) {
363             LOG.error("uncompressAllFromAppStream failed!");
364             throw new BundleException("uncompressAllFromAppStream failed!");
365         } finally {
366             Utility.closeStream(zipInputStream);
367             Utility.closeStream(outputStream);
368         }
369         return result;
370     }
371 
372     /**
373      * uncompress hap.
374      *
375      * @param utility common data
376      * @return the uncompress result
377      */
uncompressHap(Utility utility)378     static UncompressResult uncompressHap(Utility utility) {
379         UncompressResult compressResult = new UncompressResult();
380         try {
381             compressResult = uncompressHapByPath(utility.getDeviceType(), utility.getHapPath());
382         } catch (BundleException ignored) {
383             LOG.error("Uncompress::uncompressHap Bundle exception");
384             compressResult.setResult(false);
385             compressResult.setMessage("uncompressHap Bundle exception");
386         }
387         return compressResult;
388     }
389 
390     /**
391      * uncompress hap by path, it can adapt stage module and fa module.
392      *
393      * @param deviceType indicates the device type of parse type.
394      * @param hapPath indicates the hap path of hap.
395      * @return the uncompress result
396      */
uncompressHapByPath(String deviceType, String hapPath)397     static UncompressResult uncompressHapByPath(String deviceType, String hapPath) throws BundleException {
398         UncompressResult compressResult = new UncompressResult();
399         try {
400             if (isModuleHap(hapPath, compressResult)) {
401                 compressResult = unCompressModuleHap(deviceType, hapPath, MODULE_JSON);
402             } else {
403                 compressResult = uncompress(deviceType, hapPath, HARMONY_PROFILE);
404                 compressResult = obtainLabelAndIcon(compressResult);
405             }
406         } catch (BundleException e) {
407             LOG.error("Uncompress::uncompressHapByPath Bundle exception");
408             throw new BundleException("Uncompress::uncompressHapByPath failed");
409         }
410         return compressResult;
411     }
412 
413     /**
414      * uncompress hap.
415      *
416      * @param utility common data
417      * @param input the InputStream about the app package.
418      * @return the uncompress result
419      */
uncompressHapByInput(Utility utility, InputStream input)420     static UncompressResult uncompressHapByInput(Utility utility, InputStream input) {
421         UncompressResult compressResult = new UncompressResult();
422         try {
423             compressResult = uncompressHapByStream(utility.getDeviceType(), input, "");
424         } catch (BundleException ignored) {
425             LOG.error("Uncompress::uncompressHapByInput Bundle exception");
426             compressResult.setResult(false);
427             compressResult.setMessage("uncompressHapByInput Bundle exception");
428         }
429         return compressResult;
430     }
431 
432     /**
433      * uncompress hap by InputStream, it can adapt stage module and fa module.
434      *
435      * @param deviceType indicates the device type of parse type.
436      * @param stream indicates the input stream of hap.
437      * @return the uncompress result
438      */
uncompressHapByStream(String deviceType, InputStream stream, String hapName)439     static UncompressResult uncompressHapByStream(String deviceType, InputStream stream,
440                                                   String hapName) throws BundleException {
441         UncompressResult compressResult = new UncompressResult();
442         compressResult = uncompressHapByBigStream(deviceType, stream, hapName);
443         return compressResult;
444     }
445 
uncompressHapByBigStream(String deviceType, InputStream stream, String hapName)446     static UncompressResult uncompressHapByBigStream(String deviceType, InputStream stream, String hapName)
447             throws BundleException {
448         UncompressResult compressResult = new UncompressResult();
449         InputStream fileStream = null;
450         InputStream parseStream = null;
451         File file = null;
452         try {
453             String releativePath = System.getProperty("user.dir");
454             File directory = new File(releativePath);
455             file = File.createTempFile(HAP_PREFIX, HAP_SUFFIX, directory);
456             writeToTempFile(stream, file);
457             fileStream = new FileInputStream(file);
458             boolean isModule = false;
459             if (isModuleInput(fileStream)) {
460                 isModule = true;
461             }
462             parseStream = new FileInputStream(file);
463             if (isModule) {
464                 compressResult = uncompressModuleHapByInput(deviceType, parseStream, MODULE_JSON, hapName);
465             } else {
466                 compressResult = uncompressByInput(deviceType, parseStream, HARMONY_PROFILE, hapName);
467                 compressResult = obtainLabelAndIcon(compressResult);
468             }
469         } catch (IOException e) {
470             LOG.error("uncompressHapByBigStream failed for IO exception!");
471             throw new BundleException("uncompressHapByBigStream failed for IO exception!");
472         } finally {
473             Utility.closeStream(fileStream);
474             Utility.closeStream(parseStream);
475             if (file != null) {
476                 FileUtils.deleteFile(file.getPath());
477             }
478         }
479         return compressResult;
480     }
481 
482     /**
483      * unzip process
484      *
485      * @param utility common data
486      * @param srcPath source file path
487      * @param destDirPath destination file path
488      * @param suffix suffix for judgment
489      * @throws BundleException FileNotFoundException|IOException.
490      */
unzip(Utility utility, String srcPath, String destDirPath, String suffix)491     private static void unzip(Utility utility, String srcPath, String destDirPath, String suffix)
492             throws BundleException {
493         if (utility == null) {
494             LOG.error("Uncompress::unzip utility is null!");
495             throw new BundleException("Unzip failed, utility is null");
496         }
497 
498         if (srcPath.isEmpty() || !UncompressVerify.isPathValid(srcPath, true, "")) {
499             LOG.error("Uncompress::unzip srcPath is invalid!");
500             throw new BundleException("Unzip failed, srcPath is invalid");
501         }
502 
503         if (destDirPath.isEmpty() || !UncompressVerify.isPathValid(destDirPath, false, null)) {
504             LOG.error("Uncompress::unzip destDirPath is invalid!");
505             throw new BundleException("Unzip failed, destDirPath is invalid");
506         }
507         unzipFromFile(utility, srcPath, destDirPath, suffix);
508     }
509 
510     /**
511      * unzip process from the file
512      *
513      * @param utility common data
514      * @param srcPath source file path
515      * @param destDirPath destination file path
516      * @param suffix suffix for judgment
517      * @throws BundleException FileNotFoundException|IOException.
518      */
unzipFromFile(Utility utility, String srcPath, String destDirPath, String suffix)519     private static void unzipFromFile(Utility utility, String srcPath, String destDirPath, String suffix)
520             throws BundleException {
521         ZipFile zipFile = null;
522         String hapNames = "";
523         try {
524             zipFile = new ZipFile(new File(srcPath));
525             if (utility != null && !utility.getDeviceType().isEmpty()
526                     && (HAP_SUFFIX.equals(suffix) || HSP_SUFFIX.equals(suffix))) {
527                 List<PackInfo> packInfos = uncompress(utility.getDeviceType(), srcPath, PACK_INFO).getPackInfos();
528                 for (PackInfo packinfo : packInfos) {
529                     hapNames += packinfo.name + ",";
530                 }
531             }
532 
533             int entriesNum = 0;
534             for (Enumeration<? extends ZipEntry> entries = zipFile.entries(); entries.hasMoreElements();) {
535                 entriesNum++;
536                 ZipEntry entry = entries.nextElement();
537                 String entryName = "";
538                 if (entry == null || entry.getName().isEmpty()) {
539                     continue;
540                 }
541                 if (entry.getName().toLowerCase().endsWith(CUT_ENTRY_FILENAME) &&
542                     "false".equals(utility.getUnpackCutEntryApk())) {
543                     continue;
544                 }
545                 entryName = entry.getName();
546                 if (!entryName.toLowerCase(Locale.ENGLISH).endsWith(suffix) ||
547                         (!hapNames.isEmpty() && !hapNames.contains(entryName.replace(suffix, "")))) {
548                     continue;
549                 }
550                 String tempDir = destDirPath.replace(File.separator, LINUX_FILE_SEPARATOR);
551                 if (HAP_SUFFIX.equals(suffix) && "true".equals(utility.getUnpackApk())) {
552                     tempDir = tempDir + LINUX_FILE_SEPARATOR + entryName.replace(suffix, "");
553                     File destFileDir = new File(tempDir);
554                     if (!destFileDir.exists()) {
555                         destFileDir.mkdir();
556                     }
557                 }
558                 if (APK_SUFFIX.equals(suffix) && "true".equals(utility.getUnpackApk())
559                     && entryName.contains(LINUX_FILE_SEPARATOR)) {
560                     // only unpack shell apk which in the root directory
561                     continue;
562                 }
563                 String tempPath = tempDir + LINUX_FILE_SEPARATOR + entryName;
564                 if (!FileUtils.matchPattern(tempPath)) {
565                     throw new BundleException("Input invalid file " + tempPath);
566                 }
567                 File destFile = new File(tempPath);
568                 dataTransfer(zipFile, entry, destFile);
569                 if (JSON_SUFFIX.equals(suffix)) {
570                     break;
571                 } else if (HAP_SUFFIX.equals(suffix) && "true".equals(utility.getUnpackApk())) {
572                     unzip(utility, tempPath, tempDir, APK_SUFFIX);
573                     repackHap(tempPath, tempDir, entryName, utility.getUnpackApk());
574                 }
575             }
576         } catch (IOException | BundleException exception) {
577             LOG.error("Uncompress::unzipInHapMode failed: " + exception.getMessage());
578             throw new BundleException("Unzip in hap mode failed");
579         } finally {
580             Utility.closeStream(zipFile);
581         }
582     }
583 
584     /**
585      * uncompress dataTransfer
586      *
587      * @param zipFile input zip file
588      * @param entry input file in zip
589      * @param destFile output file path
590      * @throws BundleException FileNotFoundException|IOException.
591      */
dataTransfer(ZipFile zipFile, ZipEntry entry, File destFile)592     private static void dataTransfer(ZipFile zipFile, ZipEntry entry, File destFile) throws BundleException {
593         InputStream fileInputStream = null;
594         FileOutputStream fileOutStream = null;
595         try {
596             if (!FileUtils.matchPattern(destFile.getCanonicalPath())) {
597                 LOG.error("Input invalid file " + destFile);
598                 throw new BundleException("Input invalid file" + destFile.getCanonicalPath());
599             }
600             fileInputStream = zipFile.getInputStream(entry);
601             fileOutStream = new FileOutputStream(destFile);
602             byte[] data = new byte[BUFFER_SIZE];
603             int count = fileInputStream.read(data);
604             int total = 0;
605             while (count > 0) {
606                 fileOutStream.write(data, 0, count);
607                 total += count;
608                 count = fileInputStream.read(data);
609             }
610         } catch (IOException | BundleException exception) {
611             LOG.error("Uncompress::dataTransfer file " + exception.getMessage());
612             throw new BundleException("DataTransfer failed");
613         } finally {
614             Utility.closeStream(fileOutStream);
615             Utility.closeStream(fileInputStream);
616         }
617     }
618 
619     /**
620      * uncompress dataTransfer all files.
621      *
622      * @param srcPath source file path
623      * @param destDirPath destination file path
624      * @throws BundleException FileNotFoundException|IOException.
625      */
dataTransferAllFiles(String srcPath, String destDirPath)626     private static void dataTransferAllFiles(String srcPath, String destDirPath) throws BundleException {
627         ZipFile zipFile = null;
628         try {
629             if (!FileUtils.matchPattern(srcPath)) {
630                 throw new BundleException("Input invalid file " + srcPath);
631             }
632             zipFile = new ZipFile(new File(srcPath));
633             int entriesNum = 0;
634             for (Enumeration<? extends ZipEntry> entries = zipFile.entries(); entries.hasMoreElements();) {
635                 entriesNum++;
636                 ZipEntry entry = entries.nextElement();
637                 if (entry == null) {
638                     continue;
639                 }
640                 String tempPath = destDirPath + LINUX_FILE_SEPARATOR + entry.getName();
641                 File destFile = new File(tempPath);
642                 if (destFile != null && destFile.getParentFile() != null && !destFile.getParentFile().exists()) {
643                     destFile.getParentFile().mkdirs();
644                 }
645                 dataTransfer(zipFile, entry, destFile);
646             }
647         } catch (FileNotFoundException ignored) {
648             LOG.error("Uncompress::unzipApk file not found exception");
649             throw new BundleException("Unzip Apk failed");
650         } catch (IOException exception) {
651             LOG.error("Uncompress::unzipApk io exception: " + exception.getMessage());
652             throw new BundleException("Unzip Apk failed");
653         } finally {
654             Utility.closeStream(zipFile);
655         }
656     }
657 
dataTransferFilesByApp(Utility utility, String srcPath, String destDirPath)658     private static void dataTransferFilesByApp(Utility utility, String srcPath, String destDirPath)
659             throws BundleException {
660         ZipFile zipFile = null;
661         try {
662             zipFile = new ZipFile(new File(srcPath));
663             int entriesNum = 0;
664             for (Enumeration<? extends ZipEntry> entries = zipFile.entries(); entries.hasMoreElements();) {
665                 entriesNum++;
666                 ZipEntry entry = entries.nextElement();
667                 if (entry == null) {
668                     continue;
669                 }
670                 String filePath = destDirPath + LINUX_FILE_SEPARATOR + entry.getName();
671                 if (!FileUtils.matchPattern(filePath)) {
672                     throw new BundleException("Input invalid path " + filePath);
673                 }
674                 File destFile = new File(filePath);
675                 if (destFile != null && destFile.getParentFile() != null && !destFile.getParentFile().exists()) {
676                     destFile.getParentFile().mkdirs();
677                 }
678                 boolean isUnpackApk = "true".equals(utility.getUnpackApk());
679                 if (isUnpackApk && filePath.toLowerCase().endsWith(HAP_SUFFIX)) {
680                     dataTransfer(zipFile, entry, destFile);
681                     unzip(utility, filePath, destDirPath, APK_SUFFIX);
682                     String[] temp = filePath.replace("\\", "/").split("/");
683                     String hapName = "";
684                     if (temp.length > 0) {
685                         hapName = temp[temp.length - 1];
686                     }
687                     repackHap(filePath, destDirPath, hapName, utility.getUnpackApk());
688                 } else {
689                     dataTransfer(zipFile, entry, destFile);
690                 }
691             }
692         } catch (IOException | BundleException exception) {
693             LOG.error("Uncompress::unzipApk file failed " + exception.getMessage());
694             throw new BundleException("Unzip Apk failed");
695         } finally {
696             Utility.closeStream(zipFile);
697         }
698     }
699 
getResourceDataFromHap(ZipFile zipFile)700     private static byte[] getResourceDataFromHap(ZipFile zipFile) throws BundleException, IOException {
701         int entriesNum = 0;
702         InputStream indexInputStream = null;
703         try {
704             for (Enumeration<? extends ZipEntry> entries = zipFile.entries(); entries.hasMoreElements();) {
705                 entriesNum++;
706                 ZipEntry indexEntry = entries.nextElement();
707                 if (indexEntry == null) {
708                     continue;
709                 }
710                 if (indexEntry != null && !"".equals(indexEntry.getName()) &&
711                     indexEntry.getName().toLowerCase().endsWith(RESOURCE_INDEX)) {
712                     indexInputStream = zipFile.getInputStream(indexEntry);
713                     return getByte(indexInputStream);
714                 }
715             }
716         } finally {
717             Utility.closeStream(indexInputStream);
718         }
719         return null;
720     }
721 
unZipHapFileFromHapFile(String srcPath)722     private static HapZipInfo unZipHapFileFromHapFile(String srcPath)
723         throws BundleException, IOException {
724         HapZipInfo hapZipInfo = new HapZipInfo();
725         ZipFile zipFile = null;
726         if (!FileUtils.matchPattern(srcPath)) {
727             LOG.error("Input invalid path " + srcPath);
728             throw new BundleException("Input invalid path " + srcPath);
729         }
730         try {
731             File srcFile = new File(srcPath);
732             zipFile = new ZipFile(srcFile);
733             hapZipInfo.setHarmonyProfileJsonStr(FileUtils.getFileStringFromZip(HARMONY_PROFILE, zipFile));
734             hapZipInfo.setResDataBytes(getResourceDataFromHap(zipFile));
735             hapZipInfo.setPackInfoJsonStr(FileUtils.getFileStringFromZip(PACK_INFO, zipFile));
736             hapZipInfo.setHapFileName(getHapNameWithoutSuffix(srcFile.getName()));
737         }  finally {
738             Utility.closeStream(zipFile);
739         }
740         return hapZipInfo;
741     }
742 
743     /**
744      * uncompress from specified file name
745      *
746      * @param deviceType device type
747      * @param srcPath source file path
748      * @param fileName uncompress file name
749      * @return the uncompress result
750      * @throws BundleException FileNotFoundException|IOException.
751      */
uncompress(String deviceType, String srcPath, String fileName)752     private static UncompressResult uncompress(String deviceType, String srcPath, String fileName)
753             throws BundleException {
754         if (srcPath.isEmpty() || fileName.isEmpty()) {
755             LOG.error("Uncompress::uncompress srcPath, fileName is empty!");
756             throw new BundleException("Uncompress failed, srcPath or fileName is empty");
757         }
758 
759         UncompressResult result = new UncompressResult();
760         try {
761             HapZipInfo hapZipInfo = unZipHapFileFromHapFile(srcPath);
762             if (isPackInfo(fileName)) {
763                 uncompressPackInfo(deviceType, hapZipInfo, result);
764             } else {
765                 uncompressProfileInfo(hapZipInfo, result);
766             }
767         } catch (IOException exception) {
768             LOG.error("Uncompress::uncompress io exception: " + exception.getMessage());
769             throw new BundleException("Uncompress failed");
770         }
771         return result;
772     }
773 
uncompressPackInfo(String deviceType, HapZipInfo hapZipInfo, UncompressResult uncomperssResult)774     private static void uncompressPackInfo(String deviceType, HapZipInfo hapZipInfo, UncompressResult uncomperssResult)
775         throws BundleException {
776         List<PackInfo> packInfos = JsonUtil.parseHapList(deviceType, hapZipInfo.getPackInfoJsonStr());
777         uncomperssResult.setPackInfoStr(hapZipInfo.getPackInfoJsonStr());
778         uncomperssResult.setPackInfos(packInfos);
779     }
780 
uncompressProfileInfo(HapZipInfo hapZipInfo, UncompressResult uncomperssResult)781     private static void uncompressProfileInfo(HapZipInfo hapZipInfo, UncompressResult uncomperssResult)
782         throws BundleException {
783         ProfileInfo profileInfo = JsonUtil.parseProfileInfo(hapZipInfo.getHarmonyProfileJsonStr(),
784             hapZipInfo.getResDataBytes(), hapZipInfo.getPackInfoJsonStr(), hapZipInfo.getHapFileName());
785         profileInfo.hapName = hapZipInfo.getHapFileName();
786         profileInfo.appInfo.setBundleType(getFABundleType(profileInfo));
787         uncomperssResult.addProfileInfoStr(hapZipInfo.getHarmonyProfileJsonStr());
788         uncomperssResult.addProfileInfo(profileInfo);
789     }
790 
getFABundleType(ProfileInfo profileInfo)791     private static String getFABundleType(ProfileInfo profileInfo) {
792         String bundleType = "app";
793         if (profileInfo.hapInfo.distro.installationFree == 1) {
794             bundleType = "atomicService";
795         }
796         return bundleType;
797     }
798 
unZipHapFileFromInputStream(InputStream input)799     private static HapZipInfo unZipHapFileFromInputStream(InputStream input) throws BundleException, IOException {
800         BufferedInputStream bufIn = null;
801         ZipInputStream zipIn = null;
802         BufferedReader bufferedReader = null;
803         HapZipInfo hapZipInfo = new HapZipInfo();
804         try {
805             ZipEntry entry = null;
806             bufIn = new BufferedInputStream(input);
807             zipIn = new ZipInputStream(bufIn);
808             int entriesNum = 0;
809             while ((entry = zipIn.getNextEntry()) != null) {
810                 entriesNum++;
811                 if (entry.getName().toLowerCase().endsWith(RESOURCE_INDEX)) {
812                     hapZipInfo.setResDataBytes(getByte(zipIn));
813                     continue;
814                 }
815                 if (isPackInfo(entry.getName())) {
816                     bufferedReader = new BufferedReader(new InputStreamReader(zipIn));
817                     hapZipInfo.setPackInfoJsonStr(readStringFromInputStream(zipIn, bufferedReader));
818                     continue;
819                 }
820                 if (isHarmonyProfile(entry.getName())) {
821                     bufferedReader = new BufferedReader(new InputStreamReader(zipIn));
822                     hapZipInfo.setHarmonyProfileJsonStr(readStringFromInputStream(zipIn, bufferedReader));
823                 }
824             }
825         } finally {
826             Utility.closeStream(bufferedReader);
827             Utility.closeStream(bufIn);
828             Utility.closeStream(zipIn);
829         }
830         return hapZipInfo;
831     }
832 
readStringFromInputStream(ZipInputStream zipIn, BufferedReader bufferedReader)833     private static String readStringFromInputStream(ZipInputStream zipIn, BufferedReader bufferedReader)
834         throws IOException {
835         String line;
836         StringBuilder sb = new StringBuilder();
837         while ((line = bufferedReader.readLine()) != null) {
838             sb.append(line);
839         }
840         return sb.toString();
841     }
842 
843     /**
844      * uncompress process by InputStream
845      *
846      * @param deviceType device type
847      * @param input the InputStream about the package.
848      * @param fileName uncompress file name
849      * @return the uncompress result
850      * @throws BundleException FileNotFoundException|IOException.
851      */
uncompressByInput(String deviceType, InputStream input, String fileName, String hapName)852     private static UncompressResult uncompressByInput(String deviceType, InputStream input,
853                                                       String fileName, String hapName) throws BundleException {
854         UncompressResult result = new UncompressResult();
855         try {
856             HapZipInfo hapZipInfo = unZipHapFileFromInputStream(input);
857             hapZipInfo.setHapFileName(hapName);
858             if (isPackInfo(fileName)) {
859                 uncompressPackInfo(deviceType, hapZipInfo, result);
860             } else {
861                 uncompressProfileInfo(hapZipInfo, result);
862             }
863         } catch (IOException exception) {
864             LOG.error("Uncompress::uncompressByInput io exception: " + exception.getMessage());
865             throw new BundleException("Uncompress by input failed");
866         }
867         return result;
868     }
869 
870     /**
871      * uncompress process by InputStream
872      *
873      * @param deviceType device type
874      * @param input the InputStream about the package.
875      * @param fileName uncompress file name
876      * @return the module uncompress result
877      * @throws BundleException FileNotFoundException|IOException.
878      */
uncompressModuleByInput(String deviceType, InputStream input, String fileName, String hapName)879     private static ModuleResult uncompressModuleByInput(String deviceType, InputStream input,
880                                                         String fileName, String hapName) throws BundleException {
881         ModuleResult result = new ModuleResult();
882         try {
883             HapZipInfo hapZipInfo = unZipModuleHapFileFromInputStream(input);
884             hapZipInfo.setHapFileName(hapName);
885             if (isPackInfo(fileName)) {
886                 // for parse app
887             } else {
888                 uncompressModuleJsonInfo(hapZipInfo, result);
889             }
890         } catch (BundleException exception) {
891             LOG.error("Uncompress::uncompressByInput io exception: " + exception.getMessage());
892             throw new BundleException("Uncompress by input failed");
893         }
894         return result;
895     }
896 
897     /**
898      * Get entry byte array.
899      *
900      * @param zis the InputStream about the entry.
901      * @return Return the entry byte array.
902      * @throws BundleException FileNotFoundException|IOException.
903      */
getByte(InputStream zis)904     private static byte[] getByte(InputStream zis) throws BundleException {
905         ByteArrayOutputStream bos = new ByteArrayOutputStream();
906         byte[] buf = null;
907         try {
908             byte[] temp = new byte[READ_BUFFER_SIZE];
909             int length = 0;
910 
911             while ((length = zis.read(temp, 0, READ_BUFFER_SIZE)) != -1) {
912                 bos.write(temp, 0, length);
913             }
914 
915             buf = bos.toByteArray();
916         } catch (IOException e) {
917             LOG.error("Uncompress::getByte io exception: " + e.getMessage());
918             throw new BundleException("Get byte failed");
919         } finally {
920             Utility.closeStream(bos);
921         }
922         return buf;
923     }
924 
925     /**
926      * repack hap
927      *
928      * @param srcPath source file path
929      * @param destDirPath destination file path
930      * @param fileName target file name
931      * @param unpackApk unpackApk flag
932      * @throws BundleException FileNotFoundException|IOException.
933      */
repackHap(String srcPath, String destDirPath, String fileName, String unpackApk)934     private static void repackHap(String srcPath, String destDirPath, String fileName, String unpackApk)
935             throws BundleException {
936         if (srcPath.isEmpty() || destDirPath.isEmpty() || fileName.isEmpty()) {
937             LOG.error("Uncompress::repackHap srcPath, destDirPath or fileName is empty!");
938             throw new BundleException("Repack hap failed, srcPath, destDirPath or fileName is empty");
939         }
940 
941         if (!UncompressVerify.isPathValid(srcPath, true, "")) {
942             LOG.error("Uncompress::repackHap srcPath is invalid!");
943             throw new BundleException("Repack hap failed, srcPath is invalid");
944         }
945 
946         if (!UncompressVerify.isPathValid(destDirPath, false, null)) {
947             LOG.error("Uncompress::repackHap destDirPath is invalid!");
948             throw new BundleException("Repack hap failed, destDirPath is invalid");
949         }
950 
951         String tempDir = destDirPath.replace(File.separator, LINUX_FILE_SEPARATOR) + LINUX_FILE_SEPARATOR +
952                 TEMP_PATH;
953         dataTransferAllFiles(srcPath, tempDir);
954         packFilesByPath(tempDir, destDirPath, fileName, unpackApk);
955         File deleteFile = new File(tempDir);
956         deleteFile(deleteFile);
957     }
958 
959     /**
960      * compress file directory.
961      *
962      * @param srcPath source file path
963      * @param destDirPath destination file path
964      * @param fileName target file name
965      * @param unpackApk unpackApk flag
966      * @throws BundleException FileNotFoundException|IOException.
967      */
packFilesByPath(String srcPath, String destDirPath, String fileName, String unpackApk)968     private static void packFilesByPath(String srcPath, String destDirPath, String fileName, String unpackApk)
969             throws BundleException {
970         if (srcPath.isEmpty() || destDirPath.isEmpty() || fileName.isEmpty()) {
971             LOG.error("Uncompress::packFilesByPath srcPath, destDirPath or fileName is empty!");
972             throw new BundleException("Pack files by path failed, srcPath, destDirPath or fileName is empty");
973         }
974 
975         if (!UncompressVerify.isPathValid(srcPath, false, null) ||
976                 !UncompressVerify.isPathValid(destDirPath, false, null)) {
977             LOG.error("Uncompress::packFilesByPath srcPath or destDirPath is invalid!");
978             throw new BundleException("Pack files by path failed, srcPath or destDirPath is invalid");
979         }
980 
981         File srcDir = new File(srcPath);
982         File[] srcFiles = srcDir.listFiles();
983         if (srcFiles == null) {
984             return;
985         }
986         FileOutputStream fileOut = null;
987         CheckedOutputStream checkedOut = null;
988         ZipOutputStream zipOut = null;
989 
990         try {
991             String zipPath = destDirPath + LINUX_FILE_SEPARATOR + fileName;
992             if (!FileUtils.matchPattern(zipPath)) {
993                 throw new BundleException("Input invalid file" + zipPath);
994             }
995             File zipFile = new File(zipPath);
996             fileOut = new FileOutputStream(zipFile);
997             checkedOut = new CheckedOutputStream(fileOut, new CRC32());
998             zipOut = new ZipOutputStream(checkedOut);
999             for (int i = 0; i < srcFiles.length; i++) {
1000                 File srcFile = srcFiles[i];
1001                 if (srcFile.isDirectory()) {
1002                     if (srcFile.getPath().toLowerCase(Locale.ENGLISH).endsWith(LIBS_DIR_NAME)) {
1003                         compressDirectory(srcFile, "", zipOut, true);
1004                     } else {
1005                         compressDirectory(srcFile, "", zipOut, false);
1006                     }
1007                 } else {
1008                     if (srcFile.getPath().toLowerCase(Locale.ENGLISH).endsWith(APK_SUFFIX) &&
1009                         "true".equals(unpackApk)) {
1010                         continue;
1011                     }
1012                     compressFile(srcFile, "", zipOut, false);
1013                 }
1014             }
1015         } catch (FileNotFoundException | BundleException exception) {
1016             LOG.error("Uncompress::packFilesByPath " + exception.getMessage());
1017             throw new BundleException("Pack files by path failed");
1018         } finally {
1019             Utility.closeStream(zipOut);
1020             Utility.closeStream(checkedOut);
1021             Utility.closeStream(fileOut);
1022         }
1023     }
1024 
1025     /**
1026      * compress file directory.
1027      *
1028      * @param dir file directory
1029      * @param baseDir base path for file
1030      * @param zipOut zip outPutStream
1031      * @param isCompression if need compression
1032      * @throws BundleException FileNotFoundException|IOException.
1033      */
compressDirectory(File dir, String baseDir, ZipOutputStream zipOut, boolean isCompression)1034     private static void compressDirectory(File dir, String baseDir, ZipOutputStream zipOut, boolean isCompression)
1035             throws BundleException {
1036         File[] files = dir.listFiles();
1037         if (files == null) {
1038             return;
1039         }
1040         for (File file : files) {
1041             if (file.isDirectory()) {
1042                 compressDirectory(file, baseDir + dir.getName() + File.separator, zipOut, isCompression);
1043             } else {
1044                 compressFile(file, baseDir + dir.getName() + File.separator, zipOut, isCompression);
1045             }
1046         }
1047     }
1048 
1049     /**
1050      * compress process.
1051      *
1052      * @param srcFile source file to zip
1053      * @param baseDir base path for file
1054      * @param zipOut zip outPutStream
1055      * @param isCompression if need compression
1056      * @throws BundleException FileNotFoundException|IOException.
1057      */
compressFile(File srcFile, String baseDir, ZipOutputStream zipOut, boolean isCompression)1058     private static void compressFile(File srcFile, String baseDir, ZipOutputStream zipOut, boolean isCompression)
1059             throws BundleException {
1060         FileInputStream fileInputStream = null;
1061         BufferedInputStream bufferedInputStream = null;
1062 
1063         try {
1064             String entryName = (baseDir + srcFile.getName()).replace(File.separator, LINUX_FILE_SEPARATOR);
1065             ZipEntry zipEntry = new ZipEntry(entryName);
1066 	    boolean isNeedCompress = isCompression;
1067 	    if (srcFile.isFile() && srcFile.getName().toLowerCase(Locale.ENGLISH).endsWith(SO_SUFFIX)) {
1068                 isNeedCompress = false;
1069             }
1070             if (isNeedCompress) {
1071                 zipEntry.setMethod(ZipEntry.DEFLATED);
1072             } else {
1073                 zipEntry.setMethod(ZipEntry.STORED);
1074                 zipEntry.setCompressedSize(srcFile.length());
1075                 zipEntry.setSize(srcFile.length());
1076                 CRC32 crc = getCrcFromFile(srcFile);
1077                 zipEntry.setCrc(crc.getValue());
1078             }
1079             FileTime fileTime = FileTime.fromMillis(FILE_TIME);
1080             zipEntry.setLastAccessTime(fileTime);
1081             zipEntry.setLastModifiedTime(fileTime);
1082             zipOut.putNextEntry(zipEntry);
1083             byte[] data = new byte[BUFFER_SIZE];
1084             fileInputStream = new FileInputStream(srcFile);
1085             bufferedInputStream = new BufferedInputStream(fileInputStream);
1086             int count = bufferedInputStream.read(data);
1087             while (count > 0) {
1088                 zipOut.write(data, 0, count);
1089                 count = bufferedInputStream.read(data);
1090             }
1091         } catch (FileNotFoundException ignored) {
1092             LOG.error("Uncompress::compressFile file not found exception");
1093             throw new BundleException("Compress file failed");
1094         } catch (IOException exception) {
1095             LOG.error("Uncompress::compressFile io exception: " + exception.getMessage());
1096             throw new BundleException("Compress file failed");
1097         } finally {
1098             Utility.closeStream(fileInputStream);
1099             Utility.closeStream(bufferedInputStream);
1100         }
1101     }
1102 
1103     /**
1104      * get CRC32 from file.
1105      *
1106      * @param file source file
1107      * @return CRC32
1108      * @throws BundleException FileNotFoundException|IOException.
1109      */
getCrcFromFile(File file)1110     private static CRC32 getCrcFromFile(File file) throws BundleException {
1111         FileInputStream fileInputStream = null;
1112         CRC32 crc = new CRC32();
1113         try {
1114             fileInputStream = new FileInputStream(file);
1115             byte[] buffer = new byte[BUFFER_SIZE];
1116 
1117             int count = fileInputStream.read(buffer);
1118             while (count > 0) {
1119                 crc.update(buffer, 0, count);
1120                 count = fileInputStream.read(buffer);
1121             }
1122         } catch (FileNotFoundException ignored) {
1123             LOG.error("Uncompressor::getCrcFromFile file not found exception");
1124             throw new BundleException("Get Crc from file failed");
1125         } catch (IOException exception) {
1126             LOG.error("Uncompressor::getCrcFromFile io exception: " + exception.getMessage());
1127             throw new BundleException("Get Crc from file failed");
1128         } finally {
1129             Utility.closeStream(fileInputStream);
1130         }
1131         return crc;
1132     }
1133 
1134     /**
1135      * delete file
1136      *
1137      * @param file the file to be deleted
1138      */
deleteFile(File file)1139     private static void deleteFile(File file) {
1140         if (file.exists()) {
1141             if (file.isDirectory()) {
1142                 File[] files = file.listFiles();
1143                 for (int i = 0; i < files.length; i++) {
1144                     deleteFile(files[i]);
1145                 }
1146             }
1147             file.delete();
1148         }
1149     }
1150 
1151     /**
1152      * check
1153      *
1154      * @param result the result of parse app all mode
1155      * @return return the result of checkParseAllResult.
1156      */
checkParseAllResult(UncompressResult result)1157     private static UncompressResult checkParseAllResult(UncompressResult result) {
1158         UncompressResult errorResult = new UncompressResult();
1159         errorResult.setResult(false);
1160         errorResult.setMessage("App package is invalid.");
1161         if (result == null || result.getPackInfos() == null || result.getProfileInfos() == null) {
1162             return errorResult;
1163         }
1164 
1165         List<PackInfo> packInfos = result.getPackInfos();
1166         List<ProfileInfo> profileInfos = result.getProfileInfos();
1167         int packInfoSize = packInfos.size();
1168         int profileInfoSize = profileInfos.size();
1169         if (packInfoSize == 0 || profileInfoSize == 0 || packInfoSize != profileInfoSize) {
1170             LOG.error("Uncompress::checkParseAllResult error, hapNum is invalid in app");
1171             return errorResult;
1172         }
1173 
1174         for (int i = 0; i < packInfoSize; i++) {
1175             if (packInfos.get(i) == null || packInfos.get(i).name.isEmpty()) {
1176                 return errorResult;
1177             }
1178             boolean isHave = false;
1179             for (int j = 0; j < profileInfoSize; j++) {
1180                 if (profileInfos.get(j) == null || profileInfos.get(j).hapName.isEmpty()) {
1181                     return errorResult;
1182                 }
1183                 if (comparePackAndProfile(packInfos.get(i), profileInfos.get(j))) {
1184                     isHave = true;
1185                     break;
1186                 }
1187             }
1188             if (!isHave) {
1189                 return errorResult;
1190             }
1191         }
1192 
1193         return result;
1194     }
1195 
1196     /**
1197      * get label and icon for application
1198      *
1199      * @param result the result of parse app all mode
1200      * @return return the result which contains icon and label
1201      */
obtainLabelAndIcon(UncompressResult result)1202     private static UncompressResult obtainLabelAndIcon(UncompressResult result) {
1203         List<ProfileInfo> profileInfos = result.getProfileInfos();
1204         if (profileInfos.isEmpty()) {
1205             return result;
1206         }
1207         for (ProfileInfo profileInfo : profileInfos) {
1208             if (profileInfo == null) {
1209                 continue;
1210             }
1211             HapInfo hapInfo = profileInfo.hapInfo;
1212             if (hapInfo == null) {
1213                 continue;
1214             }
1215             Distro distro = hapInfo.distro;
1216             if (distro == null) {
1217                 continue;
1218             }
1219             String moduleType = distro.moduleType;
1220             if (ENTRY_TYPE.equals(moduleType.toLowerCase(Locale.ENGLISH))) {
1221                 return obtainInnerLabelAndIcon(result, hapInfo, distro);
1222             }
1223         }
1224         return result;
1225     }
1226 
1227     /**
1228      * get label and icon for application
1229      *
1230      * @param result the result of parse app all mode
1231      * @param hapInfo hap info of entry hap
1232      * @return return the result which contains icon and label
1233      */
obtainInnerLabelAndIcon(UncompressResult result, HapInfo hapInfo, Distro distro)1234     private static UncompressResult obtainInnerLabelAndIcon(UncompressResult result, HapInfo hapInfo, Distro distro) {
1235         List<AbilityInfo> abilities = hapInfo.abilities;
1236         if ((abilities == null) || (abilities.isEmpty())) {
1237             result.setLabel(distro.moduleName);
1238             return result;
1239         }
1240         int size = 0;
1241         for (AbilityInfo info : abilities) {
1242             if (info == null) {
1243                 size++;
1244                 continue;
1245             }
1246             if ((info.skills == null) || (info.skills.isEmpty())) {
1247                 continue;
1248             }
1249             for (SkillInfo skill : info.skills) {
1250                 if (skill == null) {
1251                     continue;
1252                 }
1253                 List<String> actions = skill.actions;
1254                 List<String> entities = skill.entities;
1255                 if ((!actions.isEmpty()) && (actions.contains(SYSTEM_ACTION) || actions.contains(SYSTEM_WANT_HOME))
1256                         && (!entities.isEmpty()) && (entities.contains(SYSTEM_ENTITY))) {
1257                     result.setLabel(info.label);
1258                     result.setIcon(info.icon);
1259                     return result;
1260                 }
1261             }
1262         }
1263         if (size == abilities.size()) {
1264             result.setLabel(distro.moduleName);
1265             return result;
1266         }
1267         for (AbilityInfo info : abilities) {
1268             if (info != null) {
1269                 result.setLabel(info.label);
1270                 result.setIcon(info.icon);
1271                 break;
1272             }
1273         }
1274         return result;
1275     }
1276 
1277 
isHarmonyProfile(String fileName)1278     private static boolean isHarmonyProfile(String fileName) {
1279         return HARMONY_PROFILE.equals(fileName);
1280     }
1281 
isPackInfo(String fileName)1282     private static boolean isPackInfo(String fileName) {
1283         return PACK_INFO.equals(fileName);
1284     }
1285 
getHapNameWithoutSuffix(String hapFileName)1286     private static String getHapNameWithoutSuffix(String hapFileName) {
1287         if (hapFileName == null || hapFileName.isEmpty() || hapFileName.lastIndexOf(".") == -1) {
1288             return "";
1289         }
1290         return hapFileName.substring(0, hapFileName.lastIndexOf("."));
1291     }
1292 
unZipModuleHapFile(String srcPath)1293     private static HapZipInfo unZipModuleHapFile(String srcPath)
1294             throws BundleException, IOException {
1295         HapZipInfo hapZipInfo = new HapZipInfo();
1296         ZipFile zipFile = null;
1297         try {
1298             File srcFile = new File(srcPath);
1299             zipFile = new ZipFile(srcFile);
1300             getProfileJson(zipFile, hapZipInfo.resourcemMap);
1301             hapZipInfo.setHarmonyProfileJsonStr(FileUtils.getFileStringFromZip(MODULE_JSON, zipFile));
1302             hapZipInfo.setPackInfoJsonStr(FileUtils.getFileStringFromZip(PACK_INFO, zipFile));
1303             hapZipInfo.setResDataBytes(getResourceDataFromHap(zipFile));
1304             hapZipInfo.setHapFileName(getHapNameWithoutSuffix(srcFile.getName()));
1305         } finally {
1306             Utility.closeStream(zipFile);
1307         }
1308         return hapZipInfo;
1309     }
1310 
1311     /**
1312      * uncompress from HapZipInfo
1313      *
1314      * @param hapZipInfo hap zip info
1315      * @return the parse moduleResult
1316      * @throws BundleException FileNotFoundException|IOException.
1317      */
uncompressModuleJsonInfo(HapZipInfo hapZipInfo, ModuleResult moduleResult)1318     private static void uncompressModuleJsonInfo(HapZipInfo hapZipInfo, ModuleResult moduleResult)
1319             throws BundleException {
1320         ModuleProfileInfo moduleProfileInfo = JsonUtil.parseModuleProfileInfo(hapZipInfo.getHarmonyProfileJsonStr(),
1321                 hapZipInfo.getResDataBytes(), hapZipInfo.getPackInfoJsonStr(), hapZipInfo.getHapFileName(),
1322                 hapZipInfo.resourcemMap);
1323         moduleProfileInfo.hapName = hapZipInfo.getHapFileName();
1324         moduleResult.addModuleProfileInfo(moduleProfileInfo);
1325         moduleResult.moduleProfileStr.add(hapZipInfo.getHarmonyProfileJsonStr());
1326     }
1327 
1328     /**
1329      * uncompress from specified file name
1330      *
1331      * @param deviceType device type
1332      * @param srcPath source file path
1333      * @param fileName uncompress file name
1334      * @return the uncompress result
1335      * @throws BundleException FileNotFoundException|IOException.
1336      */
uncompressModule(String deviceType, String srcPath, String fileName)1337     private static ModuleResult uncompressModule(String deviceType, String srcPath, String fileName)
1338             throws BundleException {
1339         if (srcPath.isEmpty() || fileName.isEmpty()) {
1340             LOG.error("Uncompress::uncompressModule srcPath, fileName is empty!");
1341             throw new BundleException("uncompressModule failed, srcPath or fileName is empty");
1342         }
1343         ModuleResult moduleResult = new ModuleResult();
1344         try {
1345             HapZipInfo hapZipInfo = unZipModuleHapFile(srcPath);
1346             uncompressModuleJsonInfo(hapZipInfo, moduleResult);
1347             if (moduleResult.packInfos.isEmpty() && !hapZipInfo.getPackInfoJsonStr().isEmpty()) {
1348                 moduleResult.packInfos = JsonUtil.parsePackInfos(hapZipInfo.getPackInfoJsonStr());
1349             }
1350         } catch (IOException exception) {
1351             moduleResult.setResult(false);
1352             LOG.error("Uncompress::uncompressModule parseMode is invalid!");
1353         }
1354         return moduleResult;
1355     }
1356 
1357     /**
1358      * uncompress module hap.
1359      *
1360      * @param deviceType indicates the device type of uncompress mode.
1361      * @param srcPath indicates the path type of hap.
1362      * @param fileName indicates json file name.
1363      * @return the uncompress result
1364      */
unCompressModuleHap(String deviceType, String srcPath, String fileName)1365     static UncompressResult unCompressModuleHap(String deviceType, String srcPath, String fileName)
1366             throws BundleException{
1367         if (srcPath.isEmpty() || fileName.isEmpty()) {
1368             LOG.error("Uncompress::uncompress srcPath, fileName is empty!");
1369             throw new BundleException("Uncompress failed, srcPath or fileName is empty");
1370         }
1371         UncompressResult uncomperssResult = new UncompressResult();
1372         ModuleResult moduleResult = new ModuleResult();
1373         try {
1374             moduleResult = uncompressModule(deviceType, srcPath, fileName);
1375             ModuleAdaption moduleAdaption = new ModuleAdaption();
1376             uncomperssResult = moduleAdaption.convertToUncompressResult(moduleResult);
1377         } catch (BundleException ignored) {
1378             LOG.error("Uncompress::uncompressHap Bundle exception");
1379             uncomperssResult.setResult(false);
1380             uncomperssResult.setMessage("uncompressHap Bundle exception");
1381         }
1382         return uncomperssResult;
1383     }
1384     /**
1385      * get all resource in profile.
1386      *
1387      * @param zipFile is the hap file
1388      * @return the parse resource result
1389      */
getProfileJson(ZipFile zipFile, HashMap<String, String> resourceMap)1390     static void getProfileJson(ZipFile zipFile, HashMap<String, String> resourceMap) throws BundleException {
1391         try {
1392             final Enumeration<? extends ZipEntry> entries = zipFile.entries();
1393             while (entries.hasMoreElements()) {
1394                 final ZipEntry entry = entries.nextElement();
1395                 if (entry.getName().contains(RESOURCE_PATH)) {
1396                     String filePath = entry.getName();
1397                     String fileName = filePath.replaceAll(RESOURCE_PATH, "");
1398                     String fileContent = FileUtils.getFileStringFromZip(filePath, zipFile);
1399                     resourceMap.put(fileName, fileContent);
1400                 }
1401             }
1402         } catch (IOException e) {
1403             LOG.error("Uncompress::getProfileJson IOException");
1404             throw new BundleException("Uncompress::getProfileJson failed");
1405         }
1406     }
1407 
1408     /**
1409      * uncompress module hap.
1410      *
1411      * @param deviceType indicates the deviceType of parse hap.
1412      * @param input the InputStream about the app package.
1413      * @param fileName the file name of json file.
1414      * @return the uncompress result
1415      */
uncompressModuleHapByInput(String deviceType, InputStream input, String fileName, String hapName)1416     static UncompressResult uncompressModuleHapByInput(String deviceType,
1417                                                        InputStream input, String fileName, String hapName) {
1418         UncompressResult uncompressResult = new UncompressResult();
1419         ModuleResult moduleResult = new ModuleResult();
1420         try {
1421             moduleResult = uncompressModuleByInput(deviceType, input, MODULE_JSON, hapName);
1422             ModuleAdaption moduleAdaption = new ModuleAdaption();
1423             uncompressResult = moduleAdaption.convertToUncompressResult(moduleResult);
1424         } catch (BundleException ignored) {
1425             LOG.error("Uncompress::uncompressHapByInput Bundle exception");
1426             uncompressResult.setResult(false);
1427             uncompressResult.setMessage("uncompressHapByInput Bundle exception");
1428         }
1429         return uncompressResult;
1430     }
1431 
1432     /**
1433      * unzip module hap from zip file.
1434      *
1435      * @param input Indicates the InputStream about the package.
1436      * @return Return the uncomperss result of parseHap
1437      */
unZipModuleHapFileFromInputStream(InputStream input)1438     private static HapZipInfo unZipModuleHapFileFromInputStream(InputStream input) throws BundleException {
1439         BufferedInputStream bufIn = null;
1440         ZipInputStream zipIn = null;
1441         BufferedReader bufferedReader = null;
1442         HapZipInfo hapZipInfo = new HapZipInfo();
1443         try {
1444             ZipEntry entry = null;
1445             bufIn = new BufferedInputStream(input);
1446             zipIn = new ZipInputStream(bufIn);
1447             while ((entry = zipIn.getNextEntry()) != null) {
1448                 if (entry.getName().toLowerCase().endsWith(RESOURCE_INDEX)) {
1449                     hapZipInfo.setResDataBytes(getByte(zipIn));
1450                     continue;
1451                 }
1452                 if (isPackInfo(entry.getName())) {
1453                     bufferedReader = new BufferedReader(new InputStreamReader(zipIn));
1454                     hapZipInfo.setPackInfoJsonStr(readStringFromInputStream(zipIn, bufferedReader));
1455                     continue;
1456                 }
1457                 if (MODULE_JSON.equals(entry.getName())) {
1458                     bufferedReader = new BufferedReader(new InputStreamReader(zipIn));
1459                     hapZipInfo.setHarmonyProfileJsonStr(readStringFromInputStream(zipIn, bufferedReader));
1460                 }
1461                 if (entry.getName().contains(RESOURCE_PATH)) {
1462                     bufferedReader = new BufferedReader(new InputStreamReader(zipIn));
1463                     String filePath = entry.getName();
1464                     String fileName = filePath.replaceAll(RESOURCE_PATH, "");
1465                     String fileContent = readStringFromInputStream(zipIn, bufferedReader);
1466                     hapZipInfo.pushResourceMap(fileName, fileContent);
1467                 }
1468             }
1469         } catch (BundleException | IOException e) {
1470             LOG.error("unZipModuleHapFileFromInputStream failed!");
1471             throw new BundleException("unZipModuleHapFileFromInputStream failed!");
1472         } finally {
1473             Utility.closeStream(bufferedReader);
1474             Utility.closeStream(bufIn);
1475             Utility.closeStream(zipIn);
1476         }
1477         return hapZipInfo;
1478     }
1479 
1480     /**
1481      * Parse the hap type.
1482      *
1483      * @param hapPath Indicates the hap path.
1484      * @param compressResult Indicates the result of parse hap.
1485      * @return Return the type result of isModuleHap
1486      */
isModuleHap(String hapPath, UncompressResult compressResult)1487     public static boolean isModuleHap(String hapPath, UncompressResult compressResult) {
1488         ZipFile zipFile = null;
1489         try {
1490             zipFile = new ZipFile(new File(hapPath));
1491             final Enumeration<? extends ZipEntry> entries = zipFile.entries();
1492             while (entries.hasMoreElements()) {
1493                 final ZipEntry entry = entries.nextElement();
1494                 if (MODULE_JSON.equals(entry.getName())) {
1495                     return true;
1496                 }
1497             }
1498         } catch (FileNotFoundException ignored) {
1499             LOG.error("Uncompress::isModuleHap file not found exception");
1500             compressResult.setResult(false);
1501             compressResult.setMessage("judge is module failed");
1502         } catch (IOException exception) {
1503             LOG.error("Uncompress::isModuleHap io exception: " + exception.getMessage());
1504             compressResult.setResult(false);
1505             compressResult.setMessage("judge is module failed");
1506         } finally {
1507             Utility.closeStream(zipFile);
1508         }
1509         return false;
1510     }
1511 
1512     /**
1513      * Parse the hap type.
1514      *
1515      * @param input Indicates the hap FileInputStream.
1516      * @return Return the type result of isModuleHap.
1517      */
isModuleInput(InputStream input)1518     public static boolean isModuleInput(InputStream input) throws BundleException {
1519         BufferedInputStream bufIn = null;
1520         ZipInputStream zipIn = null;
1521         BufferedReader bufferedReader = null;
1522         try {
1523             ZipEntry entry = null;
1524             bufIn = new BufferedInputStream(input);
1525             zipIn = new ZipInputStream(bufIn);
1526             while((entry = zipIn.getNextEntry()) != null) {
1527                 if (entry.getName().toLowerCase().endsWith(MODULE_JSON)) {
1528                     return true;
1529                 }
1530             }
1531         } catch (IOException ignored) {
1532             LOG.error("Uncompress::isModuleHap judge failed!");
1533             throw new BundleException("Uncompress::isModuleHap judge failed!");
1534         } finally {
1535             Utility.closeStream(bufferedReader);
1536             Utility.closeStream(bufIn);
1537             Utility.closeStream(zipIn);
1538         }
1539         return false;
1540     }
1541 
1542     /**
1543      * create file output stream from InputStream .
1544      *
1545      * @param stream Indicates the input stream of hap.
1546      * @param file Indicates the temp file to save input stream.
1547      */
writeToTempFile(InputStream stream, File file)1548     static void writeToTempFile(InputStream stream, File file) throws BundleException {
1549         FileOutputStream fileOutputStream = null;
1550         try {
1551             if (file == null) {
1552                 LOG.error("file not exist!");
1553             }
1554             fileOutputStream = new FileOutputStream(file);
1555             int bytesRead = 0;
1556             byte[] buffer = new byte[1024];
1557             while ((bytesRead = stream.read(buffer)) != -1) {
1558                 fileOutputStream.write(buffer, 0, bytesRead);
1559             }
1560         } catch (IOException e) {
1561             LOG.error("writeToTempFile failed!");
1562             throw new BundleException("writeToTempFile failed!");
1563         } finally {
1564             Utility.closeStream(fileOutputStream);
1565         }
1566     }
1567 
1568     /**
1569      * copy rpcid.sc file.
1570      *
1571      * @param srcFile Indicates the path of hap.
1572      * @param rpcidPath Indicates the output path of rpcid.sc file.
1573      */
getRpcidFromHap(String srcFile, String rpcidPath)1574     static void getRpcidFromHap(String srcFile, String rpcidPath) throws BundleException {
1575         ZipFile zipFile = null;
1576         InputStream inputStream = null;
1577         FileOutputStream outputStream = null;
1578         try {
1579             zipFile = new ZipFile(srcFile);
1580             String filePath = null;
1581             final Enumeration<? extends ZipEntry> entries = zipFile.entries();
1582             while (entries.hasMoreElements()) {
1583                 final ZipEntry entry = entries.nextElement();
1584                 if (RPCID_SC.equals(entry.getName())) {
1585                     filePath = entry.getName();
1586                     break;
1587                 }
1588             }
1589             if (filePath != null) {
1590                 File rpcidFile = new File(rpcidPath, RPCID_SC);
1591                 if (rpcidFile.getParentFile() != null && !rpcidFile.getParentFile().exists()) {
1592                     rpcidFile.getParentFile().mkdirs();
1593                 }
1594                 ZipEntry rpcidEntry = zipFile.getEntry(filePath);
1595                 inputStream = zipFile.getInputStream(rpcidEntry);
1596                 byte[] buffer = new byte[1024];
1597                 int noBytes = 0;
1598                 outputStream = new FileOutputStream(rpcidFile);
1599                 while((noBytes = inputStream.read(buffer)) != -1) {
1600                     outputStream.write(buffer, 0, noBytes);
1601                 }
1602             } else {
1603                 LOG.error("Uncompress::getRpcidFromHap hap has no rpcid.sc file");
1604                 throw new BundleException("Uncompress::getRpcidFromHap hap has no rpcid.sc file");
1605             }
1606         } catch (IOException e) {
1607             LOG.error("Uncompress::getRpcidFromHap IOException " + e.getMessage());
1608             throw new BundleException("Uncompress::getRpcidFromHap failed");
1609         } finally {
1610             Utility.closeStream(zipFile);
1611             Utility.closeStream(inputStream);
1612             Utility.closeStream(outputStream);
1613         }
1614     }
1615 
1616     /**
1617      * parse resource.index file.
1618      *
1619      * @param srcPath Indicates the path of hap.
1620      */
getResourceFromHap(String srcPath)1621     static List<ResourceIndexResult> getResourceFromHap(String srcPath) throws BundleException, IOException {
1622         ZipFile zipFile = null;
1623         try {
1624             File srcFile = new File(srcPath);
1625             zipFile = new ZipFile(srcFile);
1626             byte[] data = getResourceDataFromHap(zipFile);
1627             return ResourcesParser.getAllDataItem(data);
1628         } finally {
1629             Utility.closeStream(zipFile);
1630         }
1631     }
1632 
1633     /**
1634      * uncompress appqf file.
1635      *
1636      * @param utility is the common args for input.
1637      * @throws BundleException if uncompress failed.
1638      */
uncompressAPPQFFile(Utility utility)1639     private static void uncompressAPPQFFile(Utility utility) throws BundleException {
1640         ZipFile zipFile = null;
1641         try {
1642             zipFile = new ZipFile(new File(utility.getAPPQFPath()));
1643             int entriesNum = 0;
1644             for (Enumeration<? extends ZipEntry> entries = zipFile.entries(); entries.hasMoreElements();) {
1645                 entriesNum++;
1646                 ZipEntry entry = entries.nextElement();
1647                 if (entry == null) {
1648                     continue;
1649                 }
1650                 String filePath = utility.getOutPath() + File.separator + entry.getName();
1651                 if (!FileUtils.matchPattern(filePath)) {
1652                     LOG.error("uncompressAPPQFFile: Input invalid file" + filePath);
1653                     throw new BundleException("uncompressAPPQFFile: Input invalid file" + filePath);
1654                 }
1655                 File destFile = new File(filePath);
1656                 if (destFile != null && destFile.getParentFile() != null && !destFile.getParentFile().exists()) {
1657                     destFile.getParentFile().mkdirs();
1658                 }
1659                 dataTransfer(zipFile, entry, destFile);
1660             }
1661         } catch (FileNotFoundException ignored) {
1662             LOG.error("Uncompress::uncompressAPPQFFile file not found exception");
1663             throw new BundleException("Uncompress::uncompressAPPQFFile file not found");
1664         } catch (IOException exception) {
1665             LOG.error("Uncompress::uncompressAPPQFFile io exception");
1666             throw new BundleException("Uncompress::uncompressAPPQFFile io exception");
1667         } finally {
1668             Utility.closeStream(zipFile);
1669         }
1670     }
1671 
1672     /**
1673      * parse appqf file, .
1674      *
1675      * @param appqfPath is the path of appqf file.
1676      * @throws BundleException if uncompress failed.
1677      * @throws IOException if IOException happened.
1678      */
parseAPPQFFile(String appqfPath)1679     public static List<HQFInfo> parseAPPQFFile(String appqfPath) throws BundleException {
1680         List<String> patchList = new ArrayList<>();
1681         ZipFile zipFile = null;
1682         InputStream stream = null;
1683         ZipInputStream zipInputStream = null;
1684         try {
1685             zipFile = new ZipFile(appqfPath);
1686             Enumeration<? extends ZipEntry> entries = zipFile.entries();
1687             while (entries.hasMoreElements()) {
1688                 ZipEntry appqfEntry = entries.nextElement();
1689                 stream = zipFile.getInputStream(appqfEntry);
1690                 if (!appqfEntry.getName().endsWith(HQF_SUFFIX)) {
1691                     continue;
1692                 }
1693                 zipInputStream = new ZipInputStream(stream);
1694                 String patchJson = readPatchJson(zipInputStream);
1695                 if (patchJson == null) {
1696                     continue;
1697                 }
1698                 patchList.add(patchJson);
1699             }
1700         } catch (IOException e) {
1701             LOG.error("parseAPPQFFile failed!");
1702             throw new BundleException("parseAPPQFFile failed!");
1703         } finally {
1704             Utility.closeStream(zipFile);
1705             Utility.closeStream(stream);
1706             Utility.closeStream(zipInputStream);
1707         }
1708         return parsePatchJson(patchList);
1709     }
1710 
readPatchJson(ZipInputStream zipInputStream)1711     private static String readPatchJson(ZipInputStream zipInputStream) throws BundleException {
1712         String patchJson = null;
1713         ZipEntry hqfEntry;
1714         try {
1715             while ((hqfEntry = zipInputStream.getNextEntry()) != null) {
1716                 if (!PATCH_JSON.equals(hqfEntry.getName())) {
1717                     continue;
1718                 }
1719                 patchJson = new BufferedReader(new InputStreamReader(zipInputStream,
1720                         StandardCharsets.UTF_8)).lines().parallel()
1721                         .collect(Collectors.joining(System.lineSeparator()));
1722             }
1723         } catch (IOException e) {
1724             LOG.error("readPatchJson failed!");
1725             throw new BundleException("readPatchJson failed!");
1726         }
1727         return patchJson;
1728     }
1729 
parsePatchJson(List<String> patchList)1730     private static List<HQFInfo> parsePatchJson(List<String> patchList) throws BundleException {
1731         List<HQFInfo> hqfInfoList = new ArrayList<>();
1732         for (String patchJson : patchList) {
1733             hqfInfoList.add(JsonUtil.parsePatch(patchJson));
1734         }
1735         return hqfInfoList;
1736     }
1737 
comparePackAndProfile(PackInfo packInfo, ProfileInfo profileInfo)1738     private static boolean comparePackAndProfile(PackInfo packInfo, ProfileInfo profileInfo) {
1739         if (profileInfo.hapName.replace(HAP_SUFFIXI, "").equals(packInfo.name.replace(HAP_SUFFIXI, ""))) {
1740             return true;
1741         }
1742         if (profileInfo.hapName.replace(HSP_SUFFIX, "").equals(packInfo.name.replace(HSP_SUFFIX, ""))) {
1743             return true;
1744         }
1745         return false;
1746     }
1747 }
1748