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