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