• 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.BufferedOutputStream;
19 import java.io.BufferedInputStream;
20 import java.io.BufferedReader;
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 import java.io.OutputStream;
29 import java.nio.charset.StandardCharsets;
30 import java.nio.file.attribute.FileTime;
31 import java.util.Locale;
32 import java.util.regex.Matcher;
33 import java.util.regex.Pattern;
34 import java.util.zip.CRC32;
35 import java.util.zip.CheckedOutputStream;
36 import java.util.zip.ZipInputStream;
37 import java.util.zip.ZipEntry;
38 import java.util.zip.ZipFile;
39 import java.util.zip.ZipOutputStream;
40 import java.util.Enumeration;
41 import java.util.ArrayList;
42 import java.util.List;
43 import java.util.Arrays;
44 
45 
46 /**
47  * bundle compressor class, compress file and directory.
48  *
49  */
50 public class Compressor {
51     private static final String JSON_SUFFIX = ".json";
52     private static final String INFO_SUFFIX = ".info";
53     private static final String HAP_SUFFIX = ".hap";
54     private static final String PNG_SUFFIX = ".png";
55     private static final String UPPERCASE_PNG_SUFFIX = ".PNG";
56     private static final String CONFIG_JSON = "config.json";
57     private static final String MODULE_JSON = "module.json";
58     private static final String CODE = "code";
59     private static final String NAME = "name";
60     private static final String VERSION = "\"version\"";
61     private static final String VERSION_CODE = "\"versionCode\"";
62     private static final String NULL_DIR_NAME = "";
63     private static final String RES_DIR_NAME = "res/";
64     private static final String RESOURCES_DIR_NAME = "resources/";
65     private static final String LIBS_DIR_NAME = "libs/";
66     private static final String ASSETS_DIR_NAME = "assets/";
67     private static final String SO_DIR_NAME = "maple/";
68     private static final String SO_ARM64_DIR_NAME = "maple/arm64/";
69     private static final String LINUX_FILE_SEPARATOR = "/";
70     private static final String DISTRO = "distro";
71     private static final String FORMS = "forms";
72     private static final String MODULE_NAME = "module-name";
73     private static final String MODULE_NAME_NEW = "moduleName";
74     private static final String JSON_END = "}";
75     private static final String SEMICOLON = "\"";
76     private static final String APPLICATION = "deviceConfig";
77     private static final String COMPRESS_NATIVE_LIBS = "compressNativeLibs";
78     private static final String SHARED_LIBS_DIR_NAME = "shared_libs/";
79     private static final String DEVICE_TYPE = "deviceType";
80     private static final String DEVICE_TYPE_FITNESSWATCH = "fitnessWatch";
81     private static final String DEVICE_TYPE_FITNESSWATCH_NEW = "liteWearable";
82     private static final String COLON = ":";
83     private static final String COMMA = ",";
84     private static final String ENTRYCARD_NAME = "EntryCard/";
85     private static final String PACKINFO_NAME = "pack.info";
86     private static final String ENTRYCARD_BASE_NAME = "base";
87     private static final String ENTRYCARD_SNAPSHOT_NAME = "snapshot";
88     private static final String VERTICAL = "vertical";
89     private static final String HORIZONTAL = "horizontal";
90     private static final String CAR = "car";
91     private static final String TV = "tv";
92     private static final String SDIP = "sdip";
93     private static final String MDIP = "mdip";
94     private static final String WEARABLE = "wearable";
95     private static final String PIC_1X2 = "1x2";
96     private static final String PIC_2X2 = "2x2";
97     private static final String PIC_2X4 = "2x4";
98     private static final String PIC_4X4 = "4x4";
99     private static final String REGEX_LANGUAGE = "^[a-z]{2}$";
100     private static final String REGEX_SCRIPT = "^[A-Z][a-z]{3}$";
101     private static final String REGEX_COUNTRY = "^[A-Z]{2,3}|[0-9]{3}$";
102     private static final String REGEX_ORIENTATION = "^vertical|horizontal$";
103     private static final String REGEX_DEVICE_TYPE = "^phone|tablet|car|tv|wearable|liteWearable$";
104     private static final String REGEX_SCREEN_DENSITY = "^sdpi|mdpi|ldpi|xldpi|xxldpi$";
105     private static final String REGEX_COLOR_MODE = "^light|dark$";
106     private static final String REGEX_SHAPE = "^circle$";
107     private static final String JS_PATH = "js/";
108     private static final String ETS_PATH = "ets/";
109 
110 
111     // set timestamp to get fixed MD5
112     private static final long FILE_TIME = 1546272000000L;
113 
114     // set buffer size of each read
115     private static final int BUFFER_SIZE = 10 * 1024;
116     private static final Log LOG = new Log(Compressor.class.toString());
117     private static String versionCode = "";
118     private static String versionName = "";
119 
120     private ZipOutputStream zipOut = null;
121     private boolean mIsContain2x2EntryCard = true;
122 
123     private List<String> list = new ArrayList<String>();
124     private List<String> formNamesList = new ArrayList<String>();
125     private List<String> fileNameList = new ArrayList<String>();
126     private List<String> supportDimensionsList = Arrays.asList(PIC_1X2, PIC_2X2, PIC_2X4, PIC_4X4);
127 
128     /**
129      * check path if is a module.json file
130      *
131      * @param path   path input
132      * @return true if path is a module file
133      */
isModuleJSON(String path)134     private static boolean isModuleJSON(String path)
135     {
136         File file = new File(path);
137         if ((file.isFile()) && file.getName().equals(MODULE_JSON)) {
138             return true;
139         }
140         return false;
141     }
142 
143     /**
144      * start compress.
145      * file orders as follows:
146      * for hap: 1.config.json 2.lib 3.res 4.assets 5.*.so 6.*.dex 7.*.apk 8.resources.index
147      * for app: 1.certificate 2.signature 3.pack.info 4.hap (1 and 2 may not be used)
148      *
149      * @param utility common data
150      * @return compressProcess if compress succeed
151      */
compressProcess(Utility utility)152     public boolean compressProcess(Utility utility) {
153         boolean compressResult = true;
154         File destFile = new File(utility.getOutPath());
155 
156         // if out file directory not exist, mkdirs.
157         File outParentFile = destFile.getParentFile();
158         if ((outParentFile != null) && (!outParentFile.exists())) {
159             if (!outParentFile.mkdirs()) {
160                 LOG.error("Compressor::compressProcess create out file parent directory failed!");
161                 return false;
162             }
163         }
164 
165         FileOutputStream fileOut = null;
166         CheckedOutputStream checkedOut = null;
167         try {
168             fileOut = new FileOutputStream(destFile);
169             checkedOut = new CheckedOutputStream(fileOut, new CRC32());
170             zipOut = new ZipOutputStream(checkedOut);
171             if (Utility.MODE_HAP.equals(utility.getMode())) {
172                 if (isModuleJSON(utility.getJsonPath())) {
173                     compressHapModeForModule(utility);
174                 } else {
175                     compressHapMode(utility);
176                 }
177             } else if (Utility.MODE_HAR.equals(utility.getMode())) {
178                 compressHarMode(utility);
179             } else if (Utility.MODE_APP.equals(utility.getMode())) {
180                 compressAppMode(utility);
181             } else {
182                 compressPackResMode(utility);
183             }
184         } catch (FileNotFoundException exception) {
185             compressResult = false;
186             LOG.error("Compressor::compressProcess file not found exception" + exception.getMessage());
187         } catch (BundleException ignored) {
188             compressResult = false;
189             LOG.error("Compressor::compressProcess Bundle exception");
190         } finally {
191             closeZipOutputStream();
192             Utility.closeStream(zipOut);
193             Utility.closeStream(checkedOut);
194             Utility.closeStream(fileOut);
195         }
196 
197         // if compress failed, delete out file.
198         if (!compressResult) {
199             LOG.error("Compressor::compressProcess compress failed!");
200             if (!destFile.delete()) {
201                 LOG.error("Compressor::compressProcess delete dest file failed");
202             }
203         }
204         return compressResult;
205     }
206 
207     /**
208      * compress in hap mode.
209      *
210      * @param utility common data
211      * @throws BundleException FileNotFoundException|IOException.
212      */
compressHapMode(Utility utility)213     private void compressHapMode(Utility utility) throws BundleException {
214         pathToFile(utility, utility.getJsonPath(), NULL_DIR_NAME, false);
215 
216         pathToFile(utility, utility.getProfilePath(), NULL_DIR_NAME, false);
217 
218         if (!utility.getIndexPath().isEmpty() && !utility.getModuleName().isEmpty()) {
219             String assetsPath = ASSETS_DIR_NAME + utility.getModuleName() + LINUX_FILE_SEPARATOR;
220             pathToFile(utility, utility.getIndexPath(), assetsPath, false);
221         }
222 
223         if (!utility.getLibPath().isEmpty()) {
224             pathToFile(utility, utility.getLibPath(), LIBS_DIR_NAME, utility.isCompressNativeLibs());
225         }
226 
227         if (!utility.getFilePath().isEmpty()) {
228             pathToFile(utility, utility.getFilePath(), NULL_DIR_NAME, false);
229         }
230 
231         if (!utility.getResPath().isEmpty() && !utility.getModuleName().isEmpty()) {
232             String resPath = ASSETS_DIR_NAME + utility.getModuleName() + LINUX_FILE_SEPARATOR
233                     + RESOURCES_DIR_NAME;
234             if (DEVICE_TYPE_FITNESSWATCH.equals(utility.getDeviceType().replace("\"", "").trim()) ||
235                     DEVICE_TYPE_FITNESSWATCH_NEW.equals(utility.getDeviceType().replace("\"", "").trim())) {
236                 resPath = RES_DIR_NAME;
237             }
238             pathToFile(utility, utility.getResPath(), resPath, false);
239         }
240 
241         if (!utility.getResourcesPath().isEmpty() && !utility.getModuleName().isEmpty()) {
242             String resourcesPath = ASSETS_DIR_NAME + utility.getModuleName() + LINUX_FILE_SEPARATOR
243                     + RESOURCES_DIR_NAME;
244             pathToFile(utility, utility.getResourcesPath(), resourcesPath, false);
245         }
246 
247         if (!utility.getRpcidPath().isEmpty()) {
248             String rpcidPath = NULL_DIR_NAME;
249             pathToFile(utility, utility.getRpcidPath(), rpcidPath, false);
250         }
251 
252         if (!utility.getAssetsPath().isEmpty()) {
253             pathToFile(utility, utility.getAssetsPath(), ASSETS_DIR_NAME, false);
254         }
255 
256         if (!utility.getBinPath().isEmpty()) {
257             pathToFile(utility, utility.getBinPath(), NULL_DIR_NAME, false);
258         }
259 
260         if (!utility.getPackInfoPath().isEmpty()) {
261             pathToFile(utility, utility.getPackInfoPath(), NULL_DIR_NAME, false);
262         }
263         compressHapModeMultiple(utility);
264     }
265 
266     /**
267      * compress in hap mode for module.json.
268      *
269      * @param utility common data
270      * @throws BundleException FileNotFoundException|IOException.
271      */
compressHapModeForModule(Utility utility)272     private void compressHapModeForModule(Utility utility) throws BundleException {
273         pathToFile(utility, utility.getJsonPath(), NULL_DIR_NAME, false);
274 
275         pathToFile(utility, utility.getProfilePath(), NULL_DIR_NAME, false);
276 
277         if (!utility.getIndexPath().isEmpty() && isModuleJSON(utility.getJsonPath())) {
278             String assetsPath = NULL_DIR_NAME;
279             pathToFile(utility, utility.getIndexPath(), assetsPath, false);
280         }
281 
282         if (!utility.getLibPath().isEmpty()) {
283             pathToFile(utility, utility.getLibPath(), LIBS_DIR_NAME, utility.isCompressNativeLibs());
284         }
285 
286         if (!utility.getFilePath().isEmpty()) {
287             pathToFile(utility, utility.getFilePath(), NULL_DIR_NAME, false);
288         }
289 
290         if (!utility.getResPath().isEmpty() && !utility.getModuleName().isEmpty()) {
291             String resPath = ASSETS_DIR_NAME + utility.getModuleName() + LINUX_FILE_SEPARATOR
292                     + RESOURCES_DIR_NAME;
293             if (DEVICE_TYPE_FITNESSWATCH.equals(utility.getDeviceType().replace("\"", "").trim()) ||
294                     DEVICE_TYPE_FITNESSWATCH_NEW.equals(utility.getDeviceType().replace("\"", "").trim())) {
295                 resPath = RES_DIR_NAME;
296             }
297             pathToFile(utility, utility.getResPath(), resPath, false);
298         }
299 
300         if (!utility.getResourcesPath().isEmpty() && isModuleJSON(utility.getJsonPath())) {
301             String resourcesPath = RESOURCES_DIR_NAME;
302             pathToFile(utility, utility.getResourcesPath(), resourcesPath, false);
303         }
304         if (!utility.getJsPath().isEmpty() && isModuleJSON(utility.getJsonPath())) {
305             String jsPath = JS_PATH;
306             pathToFile(utility, utility.getJsPath(), jsPath, false);
307         }
308 
309         if (!utility.getEtsPath().isEmpty() && isModuleJSON(utility.getJsonPath())) {
310             String etsPath = ETS_PATH;
311             pathToFile(utility, utility.getEtsPath(), etsPath, false);
312         }
313 
314         if (!utility.getRpcidPath().isEmpty()) {
315             String rpcidPath = NULL_DIR_NAME;
316             pathToFile(utility, utility.getRpcidPath(), rpcidPath, false);
317         }
318 
319         if (!utility.getAssetsPath().isEmpty()) {
320             pathToFile(utility, utility.getAssetsPath(), ASSETS_DIR_NAME, false);
321         }
322 
323         if (!utility.getBinPath().isEmpty()) {
324             pathToFile(utility, utility.getBinPath(), NULL_DIR_NAME, false);
325         }
326 
327         if (!utility.getPackInfoPath().isEmpty()) {
328             pathToFile(utility, utility.getPackInfoPath(), NULL_DIR_NAME, false);
329         }
330         compressHapModeMultiple(utility);
331     }
332 
333     /**
334      * compress in hap mode multiple path.
335      *
336      * @param utility common data
337      * @throws BundleException FileNotFoundException|IOException.
338      */
compressHapModeMultiple(Utility utility)339     private void compressHapModeMultiple(Utility utility) throws BundleException {
340         for (String soPathItem : utility.getFormattedSoPathList()) {
341             pathToFile(utility, soPathItem, SO_ARM64_DIR_NAME, false);
342         }
343 
344         if (utility.getFormattedSoPathList().size() == 0 && !utility.getSoDir().isEmpty()) {
345             pathToFile(utility, utility.getSoDir(), SO_DIR_NAME, false);
346         }
347 
348         for (String soPathItem : utility.getFormattedAbilitySoPathList()) {
349             pathToFile(utility, soPathItem, NULL_DIR_NAME, false);
350         }
351 
352         for (String dexPathItem : utility.getFormattedDexPathList()) {
353             pathToFile(utility, dexPathItem, NULL_DIR_NAME, false);
354         }
355 
356         for (String abcPathItem : utility.getFormattedAbcPathList()) {
357             pathToFile(utility, abcPathItem, NULL_DIR_NAME, false);
358         }
359 
360         for (String apkPathItem : utility.getFormattedApkPathList()) {
361             pathToFile(utility, apkPathItem, NULL_DIR_NAME, false);
362         }
363 
364         for (String jarPathItem : utility.getFormattedJarPathList()) {
365             pathToFile(utility, jarPathItem, NULL_DIR_NAME, false);
366         }
367 
368         for (String txtPathItem : utility.getFormattedTxtPathList()) {
369             pathToFile(utility, txtPathItem, NULL_DIR_NAME, false);
370         }
371 
372         if (!utility.getSharedLibsPath().isEmpty()) {
373             pathToFile(utility, utility.getSharedLibsPath(), SHARED_LIBS_DIR_NAME, utility.isCompressNativeLibs());
374         }
375     }
376 
377     /**
378      * compress in har mode.
379      *
380      * @param utility common data
381      * @throws BundleException FileNotFoundException|IOException.
382      */
compressHarMode(Utility utility)383     private void compressHarMode(Utility utility) throws BundleException {
384         pathToFile(utility, utility.getJsonPath(), NULL_DIR_NAME, false);
385 
386         if (!utility.getLibPath().isEmpty()) {
387             pathToFile(utility, utility.getLibPath(), LIBS_DIR_NAME, utility.isCompressNativeLibs());
388         }
389 
390         if (!utility.getResPath().isEmpty()) {
391             pathToFile(utility, utility.getResPath(), RESOURCES_DIR_NAME, false);
392         }
393 
394         if (!utility.getResourcesPath().isEmpty()) {
395             pathToFile(utility, utility.getResourcesPath(), RESOURCES_DIR_NAME, false);
396         }
397 
398         if (!utility.getAssetsPath().isEmpty()) {
399             pathToFile(utility, utility.getAssetsPath(), ASSETS_DIR_NAME, false);
400         }
401 
402         for (String jarPathItem : utility.getFormattedJarPathList()) {
403             pathToFile(utility, jarPathItem, NULL_DIR_NAME, false);
404         }
405 
406         for (String txtPathItem : utility.getFormattedTxtPathList()) {
407             pathToFile(utility, txtPathItem, NULL_DIR_NAME, false);
408         }
409     }
410 
411     /**
412      * compress in app mode.
413      *
414      * @param utility common data
415      * @throws BundleException FileNotFoundException|IOException.
416      */
compressAppMode(Utility utility)417     private void compressAppMode(Utility utility) throws BundleException {
418         pathToFile(utility, utility.getJsonPath(), NULL_DIR_NAME, false);
419 
420         if (!utility.getCertificatePath().isEmpty()) {
421             pathToFile(utility, utility.getCertificatePath(), NULL_DIR_NAME, false);
422         }
423 
424         if (!utility.getSignaturePath().isEmpty()) {
425             pathToFile(utility, utility.getSignaturePath(), NULL_DIR_NAME, false);
426         }
427 
428         File appOutputFile = new File(utility.getOutPath().trim());
429         List<String> fileList = new ArrayList<>();
430         for (String hapPathItem : utility.getFormattedHapPathList()) {
431             File hapFile = new File(hapPathItem.trim());
432             String hapTempPath = appOutputFile.getParentFile().getParent() + File.separator + hapFile.getName();
433             fileList.add(hapTempPath);
434             try {
435                 compressPackinfoIntoHap(hapPathItem, hapTempPath, utility.getPackInfoPath());
436             } catch ( IOException e) {
437                 LOG.error("Compressor::compressAppMode compress pack.info into hap failed");
438                 throw new BundleException("Compressor::compressAppMode compress pack.info into hap failed");
439             }
440         }
441         for (String hapPath : fileList) {
442             pathToFile(utility, hapPath, NULL_DIR_NAME, false);
443         }
444 
445         for (String hapPath : fileList) {
446             deleteFile(hapPath);
447         }
448 
449         if (!utility.getEntryCardPath().isEmpty()) {
450             String entryCardPath = ENTRYCARD_NAME + utility.getModuleName() + LINUX_FILE_SEPARATOR
451                     + ENTRYCARD_BASE_NAME + ENTRYCARD_SNAPSHOT_NAME;
452             for (String entryCardPathItem : utility.getformattedEntryCardPathList()) {
453                 pathToFile(utility, entryCardPathItem, entryCardPath, true);
454             }
455         }
456 
457         if (!utility.getPackResPath().isEmpty()) {
458             pathToFile(utility, utility.getPackResPath(), NULL_DIR_NAME, false);
459         }
460         File file = new File(utility.getPackInfoPath());
461         compressFile(utility, file, NULL_DIR_NAME, false);
462     }
463 
copy(InputStream input, OutputStream output)464     private void copy(InputStream input, OutputStream output) throws IOException {
465         int bytesRead;
466         byte[] data = new byte[BUFFER_SIZE];
467         while ((bytesRead = input.read(data, 0, BUFFER_SIZE)) != -1) {
468             output.write(data, 0, bytesRead);
469         }
470     }
471 
compressPackinfoIntoHap(String hapPathItem, String outPathString, String packInfo)472     private void compressPackinfoIntoHap(String hapPathItem, String outPathString, String packInfo)
473             throws FileNotFoundException, IOException, BundleException {
474         ZipFile sourceHapFile = new ZipFile(hapPathItem);
475         ZipOutputStream append = new ZipOutputStream(new FileOutputStream(outPathString));
476         try {
477             Enumeration<? extends ZipEntry> entries = sourceHapFile.entries();
478             while (entries.hasMoreElements()) {
479                 ZipEntry zipEntry = entries.nextElement();
480                 if (zipEntry.getName() != null && PACKINFO_NAME.equals(zipEntry.getName())) {
481                     continue;
482                 }
483                 append.putNextEntry(zipEntry);
484                 if (!zipEntry.isDirectory()) {
485                     copy(sourceHapFile.getInputStream(zipEntry), append);
486                 }
487                 append.closeEntry();
488             }
489             File packInfoFile = new File(packInfo);
490             ZipEntry zipEntry = getStoredZipEntry(packInfoFile, PACKINFO_NAME);
491             append.putNextEntry(zipEntry);
492             FileInputStream in = new FileInputStream(packInfoFile);
493             try {
494                 byte[] buf = new byte[BUFFER_SIZE];
495                 int len;
496                 while ((len = in.read(buf)) != -1) {
497                     append.write(buf, 0, len);
498                 }
499             } finally {
500                 in.close();
501             }
502             append.closeEntry();
503         } catch (IOException exception) {
504             LOG.error("Compressor::compressPackinfoIntoHap io exception");
505             throw new BundleException("Compressor::compressPackinfoIntoHap io exception");
506         } finally {
507             sourceHapFile.close();
508             append.close();
509         }
510     }
511 
512     /**
513      * zipFile
514      *
515      * @param utility Utility
516      * @param path  path
517      * @param format destFileName
518      */
zipFile(String path)519     private void zipFile(String path) {
520         FileOutputStream outputStream = null;
521         ZipOutputStream out = null;
522         try {
523             File destFile = new File(path + HAP_SUFFIX);
524             File outParentFile = destFile.getParentFile();
525             if ((outParentFile != null) && (!outParentFile.exists())) {
526                 if (!outParentFile.mkdirs()) {
527                     LOG.error("Compressor::compressProcess create out file parent directory failed!");
528                 }
529             }
530             outputStream = new FileOutputStream(destFile);
531             out = new ZipOutputStream(new CheckedOutputStream(outputStream, new CRC32()));
532             out.setMethod(ZipOutputStream.STORED);
533             compress(new File(path), out, NULL_DIR_NAME, true);
534         } catch (FileNotFoundException ignored) {
535             LOG.error("zip file not found exception");
536         } finally {
537             Utility.closeStream(out);
538             Utility.closeStream(outputStream);
539             deleteFile(path);
540         }
541     }
542 
543     /**
544      *  copyFileUsingFileStreams pack.info
545      *
546      * @param source inputPath
547      * @param dest outputPath
548      *
549      */
copyFileUsingFileStreams(String source, String dest)550     private static void copyFileUsingFileStreams(String source, String dest) {
551         FileInputStream input = null;
552         FileOutputStream output = null;
553         try {
554             File inputFile = new File(source);
555             File outputFile = new File(dest, PACKINFO_NAME);
556             File outputFileParent = outputFile.getParentFile();
557             if (!outputFileParent.exists()) {
558                 outputFileParent.mkdirs();
559             }
560             if (!outputFile.exists()) {
561                 outputFile.createNewFile();
562             }
563             input = new FileInputStream(inputFile);
564             output = new FileOutputStream(outputFile);
565             byte[] buf = new byte[1024];
566             int bytesRead;
567             while ((bytesRead = input.read(buf)) != -1) {
568                 output.write(buf, 0, bytesRead);
569             }
570             input.close();
571             output.close();
572         } catch (FileNotFoundException ignored) {
573             LOG.error("copy file not found exception" + ignored.toString());
574         } catch (IOException msg) {
575             LOG.error("IOException : " + msg.getMessage());
576         } finally {
577             Utility.closeStream(input);
578             Utility.closeStream(output);
579         }
580     }
581 
582 
583     /**
584      * unzip hap package to path
585      *
586      * @param hapPath zip file
587      * @param destDir path after unzip file
588      */
unzip(final String hapPath, final String destDir)589     public static void unzip(final String hapPath, final String destDir) {
590         File file = new File(destDir);
591         if (!file.exists()) {
592             file.mkdirs();
593         }
594         ZipFile zipFile = null;
595         BufferedInputStream bis = null;
596         BufferedOutputStream bos = null;
597         FileOutputStream fos = null;
598         try {
599             zipFile = new ZipFile(hapPath);
600             Enumeration<? extends ZipEntry> entries = zipFile.entries();
601             int entriesNum = 0;
602             while (entries.hasMoreElements()) {
603                 entriesNum++;
604                 ZipEntry entry = entries.nextElement();
605                 if (entry == null) {
606                     continue;
607                 }
608                 if (entry.isDirectory()) {
609                     new File(destDir + File.separator + entry.getName()).mkdirs();
610                     continue;
611                 }
612                 bis = new BufferedInputStream(zipFile.getInputStream(entry));
613                 File newFile = new File(destDir + File.separator + entry.getName());
614                 File parent = newFile.getParentFile();
615                 if (parent != null && (!parent.exists())) {
616                     parent.mkdirs();
617                 }
618                 fos = new FileOutputStream(newFile);
619                 bos = new BufferedOutputStream(fos, BUFFER_SIZE);
620                 writeFile(bis, bos, entry);
621                 bos.flush();
622                 bos.close();
623                 fos.close();
624                 bis.close();
625             }
626         } catch (FileNotFoundException ignored) {
627             LOG.error("unzip file not found exception");
628         } catch (IOException msg) {
629             LOG.error("unzip IOException : " + msg.getMessage());
630         } finally {
631             Utility.closeStream(bos);
632             Utility.closeStream(fos);
633             Utility.closeStream(bis);
634             Utility.closeStream(zipFile);
635         }
636     }
637 
638     /**
639      *  unzipWriteFile
640      *
641      * @param bis BufferedInputStream
642      * @param bos BufferedOutputStream
643      * @param entry ZipEntry
644      * @throws IOException IO
645      */
writeFile(BufferedInputStream bis, BufferedOutputStream bos, ZipEntry entry)646     private static void writeFile(BufferedInputStream bis, BufferedOutputStream bos,
647                                 ZipEntry entry) throws IOException {
648         int count;
649         int total = 0;
650         byte[] data = new byte[BUFFER_SIZE];
651         while ((count = bis.read(data, 0, BUFFER_SIZE)) != -1) {
652             bos.write(data, 0, count);
653             total += count;
654         }
655     }
656 
657     /**
658      * delete file
659      *
660      * @param path file path which will be deleted
661      */
deleteFile(final String path)662     private static void deleteFile(final String path) {
663         File file = new File(path);
664         if (file.exists()) {
665             if (file.isDirectory()) {
666                 File[] files = file.listFiles();
667                 for (int i = 0; i < files.length; i++) {
668                     deleteFile(files[i].toString());
669                 }
670             }
671             file.delete();
672         }
673     }
674 
675     /**
676      * compress in res mode.
677      *
678      * @param utility common data
679      * @throws BundleException FileNotFoundException|IOException.
680      */
compressPackResMode(Utility utility)681     private void compressPackResMode(Utility utility) throws BundleException {
682         if (!utility.getPackInfoPath().isEmpty()) {
683             File file = new File(utility.getPackInfoPath());
684             infoSpecialProcess(utility, file);
685         }
686         if (!utility.getEntryCardPath().isEmpty()) {
687             getFileList(utility.getEntryCardPath());
688             if (!mIsContain2x2EntryCard) {
689                 LOG.error("Compressor::compressPackResMode No 2x2 resource file exists");
690                 throw new BundleException("No 2x2 resource file exists");
691             }
692             for (String fileName : fileNameList) {
693                 if (fileName.endsWith(PNG_SUFFIX) || fileName.endsWith(UPPERCASE_PNG_SUFFIX)) {
694                     String fName = fileName.trim();
695                     String[] temp = fName.replace("\\", "/").split("/");
696                     if (temp.length < 4) {
697                         LOG.error("Compressor::compressPackResMode the hap file path is invalid, length: "
698                             + temp.length);
699                         continue;
700                     }
701                     String moduleName = temp[temp.length - 4];
702                     if (!isModelName(moduleName)) {
703                         LOG.error("Compressor::compressProcess compress pack.res failed, moduleName "
704                             + moduleName + " is error, please check it in config.json");
705                         throw new BundleException("Compress pack.res failed, moduleName Error");
706                     }
707                     String fileLanguageCountryName = temp[temp.length - 3];
708                     if (!isThirdLevelDirectoryNameValid(fileLanguageCountryName)) {
709                         LOG.error("Compressor::compressProcess compress failed third level directory name: "
710                             + fileLanguageCountryName + " is invalid, please check it with reference to this example: "
711                             + "zh_Hani_CN-vertical-car-mdpi-dark or zh_Hani_CN-vertical-car-mdpi");
712                         throw new BundleException("Compress failed third level directory name Error!");
713                     }
714                     String filePicturingName = temp[temp.length - 1];
715                     if (!isPicturing(filePicturingName, utility)) {
716                         LOG.error("Compressor::compressProcess Compress pack.res failed, Invalid resource file" +
717                             " name: " + filePicturingName + ", correct format example is formName-2x2.png");
718                         throw new BundleException("Compress pack.res failed, Invalid resource file name: "
719                             + filePicturingName + ", correct format example is formName-2x2.png");
720                     }
721 
722                 } else {
723                     LOG.error("Compressor::compressProcess compress failed No image in PNG format is found!");
724                     throw new BundleException("Compress pack.res failed, compress failed No image in"
725                         + " PNG format is found");
726                 }
727             }
728             pathToFile(utility, utility.getEntryCardPath(), ENTRYCARD_NAME, false);
729         }
730     }
731 
732     /**
733      * Check whether modelname meets specifications.
734      *
735      * @param name modelName
736      * @return false and true
737      */
isModelName(String name)738     private boolean isModelName(String name) {
739         for (String listName : list) {
740             if (name.equals(listName)) {
741                 return true;
742             }
743         }
744         return false;
745     }
746 
isThirdLevelDirectoryNameValid(String thirdLevelDirectoryName)747     private boolean isThirdLevelDirectoryNameValid(String thirdLevelDirectoryName) {
748         if (thirdLevelDirectoryName == null || thirdLevelDirectoryName.isEmpty()) {
749             return false;
750         }
751         if (ENTRYCARD_BASE_NAME.equals(thirdLevelDirectoryName)) {
752             return true;
753         }
754         // example: zh_Hani_CN-vertical-car-mdpi-dark or zh_Hani_CN-vertical-car-mdpi
755         int firstDelimiterIndex = thirdLevelDirectoryName.indexOf("_");
756         if (firstDelimiterIndex < 0) {
757             return false;
758         }
759         String language = thirdLevelDirectoryName.substring(0, firstDelimiterIndex);
760         int secondDelimiterIndex = thirdLevelDirectoryName.indexOf("_", firstDelimiterIndex + 1);
761         if (secondDelimiterIndex < 0) {
762             return false;
763         }
764         String script = thirdLevelDirectoryName.substring(firstDelimiterIndex + 1, secondDelimiterIndex);
765         int thirdDelimiterIndex = thirdLevelDirectoryName.indexOf("-", secondDelimiterIndex + 1);
766         if (thirdDelimiterIndex < 0) {
767             return false;
768         }
769         String country = thirdLevelDirectoryName.substring(secondDelimiterIndex + 1, thirdDelimiterIndex);
770         if (!checkLanguage(language) || !checkScript(script) || !checkCountry(country)) {
771             return false;
772         }
773         int forthDelimiterIndex = thirdLevelDirectoryName.indexOf("-", thirdDelimiterIndex + 1);
774         if (forthDelimiterIndex < 0) {
775             return false;
776         }
777         String orientation = thirdLevelDirectoryName.substring(thirdDelimiterIndex + 1, forthDelimiterIndex);
778         int fifthDelimiterIndex = thirdLevelDirectoryName.indexOf("-", forthDelimiterIndex + 1);
779         if (fifthDelimiterIndex < 0) {
780             return false;
781         }
782         String deviceType = thirdLevelDirectoryName.substring(forthDelimiterIndex + 1, fifthDelimiterIndex);
783         if (!checkOrientation(orientation) || !checkDeviceType(deviceType)) {
784             return false;
785         }
786         int sixthDelimiterIndex = thirdLevelDirectoryName.indexOf("-", fifthDelimiterIndex + 1);
787         if (sixthDelimiterIndex < 0) {
788             String screenDensity = thirdLevelDirectoryName.substring(fifthDelimiterIndex + 1,
789                     thirdLevelDirectoryName.length());
790             return checkScreenDensity(screenDensity);
791         } else {
792             String screenDensity = thirdLevelDirectoryName.substring(fifthDelimiterIndex + 1, sixthDelimiterIndex);
793             if (!checkScreenDensity(screenDensity)) {
794                 return false;
795             }
796         }
797         int seventhDelimiterIndex = thirdLevelDirectoryName.indexOf("-", sixthDelimiterIndex + 1);
798         if (seventhDelimiterIndex < 0) {
799             String tmp = thirdLevelDirectoryName.substring(sixthDelimiterIndex + 1, thirdLevelDirectoryName.length());
800             return checkColorModeOrShape(tmp);
801         }
802         if (!checkColorMode(thirdLevelDirectoryName.substring(sixthDelimiterIndex + 1, seventhDelimiterIndex))) {
803             return false;
804         }
805         String shape = thirdLevelDirectoryName.substring(seventhDelimiterIndex + 1, thirdLevelDirectoryName.length());
806         return checkShape(shape);
807     }
808 
checkLanguage(String language)809     private boolean checkLanguage(String language) {
810         if (!Pattern.compile(REGEX_LANGUAGE).matcher(language).matches()) {
811             LOG.error("Compressor::compressProcess language " + language + " is not in ISO 639-1 list");
812             return false;
813         }
814         return true;
815     }
816 
checkScript(String script)817     private boolean checkScript(String script) {
818         if (!Pattern.compile(REGEX_SCRIPT).matcher(script).matches()) {
819             LOG.error("Compressor::compressProcess script " + script + " is not in ISO 15924 list");
820             return false;
821         }
822         return true;
823     }
824 
checkCountry(String country)825     private boolean checkCountry(String country) {
826         if (!Pattern.compile(REGEX_COUNTRY).matcher(country).matches()) {
827             LOG.error("Compressor::compressProcess country " + country + " is not in ISO 3166-1 list");
828             return false;
829         }
830         return true;
831     }
832 
checkOrientation(String orientation)833     private boolean checkOrientation(String orientation) {
834         if (!Pattern.compile(REGEX_ORIENTATION).matcher(orientation).matches()) {
835             LOG.error("Compressor::compressProcess orientation " + orientation +
836                 " is not in {vertical, horizontal} list");
837             return false;
838         }
839         return true;
840     }
841 
checkDeviceType(String deviceType)842     private boolean checkDeviceType(String deviceType) {
843         if (!Pattern.compile(REGEX_DEVICE_TYPE).matcher(deviceType).matches()) {
844             LOG.error("Compressor::compressProcess deviceType " + deviceType +
845                     " is not in {phone, tablet, car, tv, wearable, liteWearable} list");
846             return false;
847         }
848         return true;
849     }
850 
checkScreenDensity(String screenDensity)851     private boolean checkScreenDensity(String screenDensity) {
852         if (!Pattern.compile(REGEX_SCREEN_DENSITY).matcher(screenDensity).matches()) {
853             LOG.error("Compressor::compressProcess screenDensity " + screenDensity +
854                     " is not in {sdpi, mdpi, ldpi, xldpi, xxldpi} list");
855             return false;
856         }
857         return true;
858     }
859 
checkColorMode(String colorMode)860     private boolean checkColorMode(String colorMode) {
861         if (!Pattern.compile(REGEX_COLOR_MODE).matcher(colorMode).matches()) {
862             LOG.error("Compressor::compressProcess colorMode " + colorMode +
863                     " is not in {light, dark} list");
864             return false;
865         }
866         return true;
867     }
868 
checkColorModeOrShape(String tmp)869     private boolean checkColorModeOrShape(String tmp) {
870         if (Pattern.compile(REGEX_COLOR_MODE).matcher(tmp).matches() ||
871             Pattern.compile(REGEX_SHAPE).matcher(tmp).matches()) {
872             return true;
873         }
874         LOG.error("Compressor::compressProcess " + tmp +
875                 " is neither in colorMode list {light, dark} nor in shape list {circle}");
876         return false;
877     }
878 
checkShape(String shape)879     private boolean checkShape(String shape) {
880         if (Pattern.compile(REGEX_SHAPE).matcher(shape).matches()) {
881             return true;
882         }
883         LOG.error("Compressor::compressProcess shape" + shape + " is not in {circle} list");
884         return false;
885     }
886 
887     /**
888      * Check whether languageCountryName meets specifications.
889      *
890      * @param name languageCountryName
891      * @return false and true
892      */
isLanguageCountry(String name)893     private boolean isLanguageCountry(String name) {
894         if (!name.equals(ENTRYCARD_BASE_NAME)) {
895             boolean isLanguage = false;
896             String[] str = name.split("-");
897             if (str.length > 1) {
898                 Locale[] ls = Locale.getAvailableLocales();
899                 for (int i = 0; i < ls.length; i++) {
900                     if (ls[i].toString().equals(str[0])) {
901                         isLanguage = true;
902                     }
903                 }
904                 if (str[1].equals( VERTICAL ) || str[1].equals( HORIZONTAL )) {
905                     isLanguage = true;
906                 }
907                 if (str[2].equals( CAR ) || str[2].equals( TV ) || str[2].equals( WEARABLE )) {
908                     isLanguage = true;
909                 }
910                 if (str[3].equals( SDIP ) || str[3].equals( MDIP )) {
911                     isLanguage = true;
912                 }
913                 return isLanguage;
914             } else {
915                 return false;
916             }
917         } else {
918             return true;
919         }
920     }
921 
922     /**
923      * Check whether picturingName meets specifications.
924      *
925      * @param name picturingName
926      * @param utility common data
927      * @return false and true
928      */
isPicturing(String name, Utility utility)929     private boolean isPicturing(String name, Utility utility) {
930         boolean isSpecifications = false;
931         if (name == null || name.isEmpty()) {
932             return isSpecifications;
933         }
934         if (!name.endsWith(PNG_SUFFIX) && !name.endsWith(UPPERCASE_PNG_SUFFIX)) {
935             LOG.error("isPicturing: the suffix is not .png or .PNG");
936             return false;
937         }
938         int delimiterIndex = name.lastIndexOf("-");
939         if (delimiterIndex < 0) {
940             LOG.error("isPicturing: the entry card naming format is invalid and should be separated by '-'!");
941             return false;
942         }
943         String formName = name.substring(0, delimiterIndex);
944         if (!utility.getFormNameList().contains(formName)) {
945             LOG.error("isPicturing: the name is not same as formName, name: " + formName + " is not in " +
946                 utility.getFormNameList().toString());
947             return false;
948         }
949         String dimension = name.substring(delimiterIndex + 1, name.lastIndexOf("."));
950         if (!supportDimensionsList.contains(dimension)) {
951             LOG.error("isPicturing: the dimension: " + dimension + " is invalid, is not in the following list: "
952                 + "{1X2, 2X2, 2X4, 4X4}");
953             return false;
954         }
955         return true;
956     }
957 
getFileList(final String filePath)958     private void getFileList(final String filePath) throws BundleException {
959         File file = new File(filePath);
960         if (!file.exists()) {
961             LOG.error("getFileList: file is not exists");
962             return;
963         }
964         File[] files = file.listFiles();
965         if (files == null) {
966             LOG.error("getFileList: no file in this file path");
967             return;
968         }
969         for (File f : files) {
970             try {
971                 if (f.isFile()) {
972                     if (f.getName().endsWith(".DS_Store")) {
973                         deleteFile(f.getCanonicalPath());
974                         continue;
975                     }
976                     String snapshotDirectoryName = f.getParentFile().getName();
977                     if (!ENTRYCARD_SNAPSHOT_NAME.equals(snapshotDirectoryName)) {
978                         LOG.error("The level-4 directory of EntryCard must be named as snapshot" +
979                             ", but current is: " + snapshotDirectoryName);
980                         throw new BundleException("The level-4 directory of EntryCard must be named as snapshot" +
981                             ", but current is: " + snapshotDirectoryName);
982                     }
983                     checkContain2x2EntryCard(f.getParentFile());
984                     fileNameList.add(f.getCanonicalPath());
985                 } else if (f.isDirectory()) {
986                     getFileList(f.getCanonicalPath());
987                 } else {
988                     LOG.error("It's not file or directory!");
989                 }
990             } catch (IOException msg) {
991                 LOG.error("IOException error: " + msg.getMessage());
992                 return;
993             }
994         }
995     }
996 
checkContain2x2EntryCard(final File snapshotDirectory)997     private void checkContain2x2EntryCard(final File snapshotDirectory) throws IOException, BundleException {
998         if (!snapshotDirectory.exists()) {
999             LOG.error("checkContain2x2EntryCard: file is not exist: " + snapshotDirectory.getName());
1000             throw new BundleException("checkContain2x2EntryCard: file is not exist");
1001         }
1002         File[] files = snapshotDirectory.listFiles();
1003         if (files == null) {
1004             LOG.error("checkContain2x2EntryCard: no file in this file path");
1005             throw new BundleException("checkContain2x2EntryCard: no file in this file path");
1006         }
1007 
1008         for (File entryCardFile : files) {
1009             if (entryCardFile.isFile() && entryCardFile.getName().contains(PIC_2X2)) {
1010                 return;
1011             }
1012         }
1013         mIsContain2x2EntryCard = false;
1014         LOG.error("checkContain2x2EntryCard: must contain 2x2 entryCard, please check it in "
1015             + snapshotDirectory.getCanonicalPath());
1016         throw new BundleException("checkContain2x2EntryCard: must contain 2x2 entryCard, please check it in "
1017             + snapshotDirectory.getCanonicalPath());
1018     }
1019 
1020     /**
1021      * compress file or directory.
1022      *
1023      * @param utility       common data
1024      * @param path          create new file by path
1025      * @param baseDir       base path for file
1026      * @param isCompression if need compression
1027      * @throws BundleException FileNotFoundException|IOException.
1028      */
pathToFile(Utility utility, String path, String baseDir, boolean isCompression)1029     private void pathToFile(Utility utility, String path, String baseDir, boolean isCompression)
1030             throws BundleException {
1031         if (path.isEmpty()) {
1032             return;
1033         }
1034         File fileItem = new File(path);
1035         if (fileItem.isDirectory()) {
1036             File[] files = fileItem.listFiles();
1037             if (files == null) {
1038                 return;
1039             }
1040             for (File file : files) {
1041                 if (file.isDirectory()) {
1042                     compressDirectory(utility, file, baseDir, isCompression);
1043                 } else if (isCompression) {
1044                     compressFile(utility, file, baseDir, isCompression);
1045                 } else {
1046                     compressFile(utility, file, baseDir, isCompression);
1047                 }
1048             }
1049         } else {
1050             compressFile(utility, fileItem, baseDir, isCompression);
1051         }
1052     }
1053 
1054     /**
1055      * compress file directory.
1056      *
1057      * @param utility       common data
1058      * @param dir           file directory
1059      * @param baseDir       current directory name
1060      * @param isCompression if need compression
1061      * @throws BundleException FileNotFoundException|IOException.
1062      */
compressDirectory(Utility utility, File dir, String baseDir, boolean isCompression)1063     private void compressDirectory(Utility utility, File dir, String baseDir, boolean isCompression)
1064             throws BundleException {
1065         File[] files = dir.listFiles();
1066         if (files == null) {
1067             return;
1068         }
1069         for (File file : files) {
1070             if (file.isDirectory()) {
1071                 compressDirectory(utility, file, baseDir + dir.getName() + File.separator, isCompression);
1072             } else {
1073                 compressFile(utility, file, baseDir + dir.getName() + File.separator, isCompression);
1074             }
1075         }
1076     }
1077 
1078     /**
1079      * compress pack.info
1080      *
1081      * @param sourceFile source
1082      * @param zipOutputStream ZipOutputStream
1083      * @param name filename
1084      * @param KeepDirStructure Empty File
1085      */
compress(File sourceFile, ZipOutputStream zipOutputStream, String name, boolean KeepDirStructure)1086     private void compress(File sourceFile, ZipOutputStream zipOutputStream, String name,
1087                                 boolean KeepDirStructure) {
1088         FileInputStream in = null;
1089         try {
1090             byte[] buf = new byte[BUFFER_SIZE];
1091             if (sourceFile.isFile()) {
1092                 ZipEntry zipEntry = getStoredZipEntry(sourceFile, name);
1093                 zipOutputStream.putNextEntry(zipEntry);
1094                 in = new FileInputStream(sourceFile);
1095                 int len;
1096                 while ((len = in.read(buf)) != -1) {
1097                     zipOutputStream.write(buf, 0, len);
1098                 }
1099                 zipOutputStream.closeEntry();
1100             } else {
1101                 File[] listFiles = sourceFile.listFiles();
1102                 if (listFiles == null || listFiles.length == 0) {
1103                     if (KeepDirStructure) {
1104                         if (!name.isEmpty()) {
1105                             ZipEntry zipEntry = getStoredZipEntry(sourceFile, name + "/");
1106                             zipOutputStream.putNextEntry(zipEntry);
1107                         } else {
1108                             ZipEntry zipEntry = getStoredZipEntry(sourceFile, name);
1109                             zipOutputStream.putNextEntry(zipEntry);
1110                         }
1111                         zipOutputStream.closeEntry();
1112                     }
1113                 } else {
1114                     for (File file : listFiles) {
1115                         if (KeepDirStructure) {
1116                             isNameEmpty(zipOutputStream, name, KeepDirStructure, file);
1117                         } else {
1118                             compress(file, zipOutputStream, file.getName(), KeepDirStructure);
1119                         }
1120                     }
1121                 }
1122             }
1123         } catch (FileNotFoundException ignored) {
1124             LOG.error("Compressor::compressFile file not found exception");
1125         } catch (IOException exception) {
1126             LOG.error("Compressor::compressFile io exception: " + exception.getMessage());
1127         } catch (BundleException bundleException) {
1128             LOG.error("Compressor::compressFile bundle exception" + bundleException.getMessage());
1129         } finally {
1130             Utility.closeStream(in);
1131         }
1132     }
1133 
getStoredZipEntry(File sourceFile, String name)1134     private ZipEntry getStoredZipEntry(File sourceFile, String name) throws BundleException {
1135         ZipEntry zipEntry = new ZipEntry(name);
1136         zipEntry.setMethod(ZipEntry.STORED);
1137         zipEntry.setCompressedSize(sourceFile.length());
1138         zipEntry.setSize(sourceFile.length());
1139         CRC32 crc = getCrcFromFile(sourceFile);
1140         zipEntry.setCrc(crc.getValue());
1141         FileTime fileTime = FileTime.fromMillis(FILE_TIME);
1142         zipEntry.setLastAccessTime(fileTime);
1143         zipEntry.setLastModifiedTime(fileTime);
1144         return zipEntry;
1145     }
1146 
getCrcFromFile(File file)1147     private CRC32 getCrcFromFile(File file) throws BundleException {
1148         FileInputStream fileInputStream = null;
1149         CRC32 crc = new CRC32();
1150         try {
1151             fileInputStream = new FileInputStream(file);
1152             byte[] buffer = new byte[BUFFER_SIZE];
1153 
1154             int count = fileInputStream.read(buffer);
1155             while (count > 0) {
1156                 crc.update(buffer, 0, count);
1157                 count = fileInputStream.read(buffer);
1158             }
1159         } catch (FileNotFoundException ignored) {
1160             LOG.error("Uncompressor::getCrcFromFile file not found exception");
1161             throw new BundleException("Get Crc from file failed");
1162         } catch (IOException exception) {
1163             LOG.error("Uncompressor::getCrcFromFile io exception: " + exception.getMessage());
1164             throw new BundleException("Get Crc from file failed");
1165         } finally {
1166             Utility.closeStream(fileInputStream);
1167         }
1168         return crc;
1169     }
1170 
1171     /**
1172      * isNameEmpty
1173      *
1174      * @param zipOutputStream ZipOutputStream
1175      * @param name filename
1176      * @param KeepDirStructure KeepDirStructure
1177      * @param file file
1178      */
isNameEmpty(ZipOutputStream zipOutputStream, String name, boolean KeepDirStructure, File file)1179     private void isNameEmpty(ZipOutputStream zipOutputStream, String name, boolean KeepDirStructure, File file) {
1180         if (!name.isEmpty()) {
1181             compress(file, zipOutputStream, name + "/" + file.getName(), KeepDirStructure);
1182         } else {
1183             compress(file, zipOutputStream, file.getName(), KeepDirStructure);
1184         }
1185     }
1186 
1187 
1188     /**
1189      * compress process.
1190      *
1191      * @param utility       common data
1192      * @param srcFile       source file to zip
1193      * @param baseDir       current directory name of file
1194      * @param isCompression if need compression
1195      * @throws BundleException FileNotFoundException|IOException.
1196      */
compressFile(Utility utility, File srcFile, String baseDir, boolean isCompression)1197     private void compressFile(Utility utility, File srcFile, String baseDir, boolean isCompression)
1198             throws BundleException {
1199         BufferedInputStream bufferedInputStream = null;
1200         FileInputStream fileInputStream = null;
1201         try {
1202             String entryName = (baseDir + srcFile.getName()).replace(File.separator, LINUX_FILE_SEPARATOR);
1203             ZipEntry zipEntry = new ZipEntry(entryName);
1204             obtainModuleVersion(utility, srcFile, entryName);
1205             if (!utility.getIsModuleJson()) {
1206                 if (!checkVersionInHaps(utility, srcFile, entryName)) {
1207                     LOG.error("Compressor::compressFile file checkVersionCodeInHaps failed");
1208                     throw new BundleException("Compressor::compressFile There are some haps with different version code!");
1209                 }
1210             }
1211             if (srcFile.getName().toLowerCase(Locale.ENGLISH).endsWith(JSON_SUFFIX)) {
1212                 zipEntry.setMethod(ZipEntry.STORED);
1213                 jsonSpecialProcess(utility, srcFile, zipEntry);
1214                 return;
1215             }
1216 
1217             if (isCompression) {
1218                 zipEntry.setMethod(ZipEntry.DEFLATED);
1219             } else {
1220                 zipEntry.setMethod(ZipEntry.STORED);
1221 
1222                 // update size
1223                 zipEntry.setCompressedSize(srcFile.length());
1224                 zipEntry.setSize(srcFile.length());
1225 
1226                 // update crc
1227                 CRC32 crc = getCrcFromFile(utility, srcFile);
1228                 zipEntry.setCrc(crc.getValue());
1229             }
1230 
1231             // update fileTime
1232             FileTime fileTime = FileTime.fromMillis(FILE_TIME);
1233             zipEntry.setLastAccessTime(fileTime);
1234             zipEntry.setLastModifiedTime(fileTime);
1235 
1236             zipOut.putNextEntry(zipEntry);
1237             byte[] data = new byte[BUFFER_SIZE];
1238             fileInputStream = new FileInputStream(srcFile);
1239             bufferedInputStream = new BufferedInputStream(fileInputStream);
1240 
1241             int count = bufferedInputStream.read(data);
1242             while (count > 0) {
1243                 zipOut.write(data, 0, count);
1244                 count = bufferedInputStream.read(data);
1245             }
1246         } catch (FileNotFoundException ignored) {
1247             LOG.error("Compressor::compressFile file not found exception");
1248             throw new BundleException("CoompressFile failed");
1249         } catch (IOException exception) {
1250             LOG.error("Compressor::compressFile io exception: " + exception.getMessage());
1251             throw new BundleException("CoompressFile failed");
1252         } finally {
1253             Utility.closeStream(bufferedInputStream);
1254             Utility.closeStream(fileInputStream);
1255         }
1256     }
1257 
1258     /**
1259      * check json type code in haps.
1260      *
1261      * @param utility common data
1262      * @param srcFile source file to zip
1263      * @param baseDir current directory name of file
1264      * @return true is for successful and false is for failed
1265      * @throws BundleException FileNotFoundException|IOException.
1266      */
obtainModuleVersion(Utility utility, File srcFile, String baseDir)1267      private void obtainModuleVersion(Utility utility, File srcFile, String baseDir) throws BundleException {
1268          String moduleJson = "";
1269          moduleJson = checkModuleTypeInHaps(utility, srcFile, baseDir);
1270          if (utility.getIsModuleJson() && !moduleJson.equals("")) {
1271              Version version = ModuleJsonUtil.getVersion(moduleJson);
1272 
1273              if (utility.getVersionCode() == -1) {
1274                  utility.setVersionCode(version.versionCode);
1275              }
1276              if (utility.getVersionName().equals("")) {
1277                  utility.setVersionName(version.versionName);
1278              }
1279              if (!checkModuleVersion(utility, version)) {
1280                  LOG.error("Compressor::checkModuleVersion failed ");
1281                  throw new BundleException("Compressor::compressFile There are some haps with different version code!");
1282              }
1283          }
1284      }
1285 
1286 
1287     /**
1288      * check version in haps.
1289      *
1290      * @param utility common data
1291      * @param version current hap version
1292      * @throws BundleException FileNotFoundException|IOException.
1293      */
checkModuleVersion(Utility utility, Version version)1294     private boolean checkModuleVersion(Utility utility, Version version) {
1295         if (version.versionName.equals("") || version.versionCode == -1) {
1296             return false;
1297         }
1298         if (!utility.getVersionName().equals(version.versionName)) {
1299             LOG.error("Compressor::checkModuleVersion versionName failed ");
1300             return false;
1301         }
1302         if (utility.getVersionCode() != version.versionCode) {
1303             LOG.error("Compressor::checkModuleVersion versionCode failed ");
1304             return false;
1305         }
1306         return true;
1307     }
1308 
1309     /**
1310      * check json type code in haps.
1311      *
1312      * @param utility common data
1313      * @param srcFile source file to zip
1314      * @param baseDir current directory name of file
1315      * @return true is for successful and false is for failed
1316      * @throws BundleException FileNotFoundException|IOException.
1317      */
checkModuleTypeInHaps(Utility utility, File srcFile, String baseDir)1318     private String checkModuleTypeInHaps(Utility utility, File srcFile, String baseDir) throws BundleException {
1319         String fileStr = srcFile.getPath();
1320         if (!fileStr.toLowerCase(Locale.ENGLISH).endsWith(HAP_SUFFIX)) {
1321             return "";
1322         }
1323         ZipFile zipFile = null;
1324         FileInputStream zipInput = null;
1325         ZipInputStream zin = null;
1326         InputStream inputStream = null;
1327         InputStreamReader reader = null;
1328         BufferedReader br = null;
1329         ZipEntry entry = null;
1330         String moduleJson = "";
1331         try {
1332             zipFile = new ZipFile(srcFile);
1333             zipInput = new FileInputStream(fileStr);
1334             zin = new ZipInputStream(zipInput);
1335             while ((entry = zin.getNextEntry()) != null) {
1336                 if (entry.getName().toLowerCase().equals(MODULE_JSON)) {
1337                     utility.setIsModuleJson(true);
1338                     inputStream = zipFile.getInputStream(entry);
1339                     reader = new InputStreamReader(inputStream);
1340                     br = new BufferedReader(reader);
1341                     if (br != null) {
1342                         moduleJson = br.readLine();
1343                         break;
1344                     }
1345                 }
1346             }
1347         } catch (IOException exception) {
1348             LOG.error("Compressor::checkModuleTypeInHaps io exception: " + exception.getMessage());
1349             throw new BundleException("Compressor::checkModuleTypeInHaps failed");
1350         } finally {
1351             Utility.closeStream(zipFile);
1352             Utility.closeStream(zipInput);
1353             Utility.closeStream(zin);
1354             Utility.closeStream(inputStream);
1355             Utility.closeStream(reader);
1356             Utility.closeStream(br);
1357         }
1358         return moduleJson;
1359     }
1360 
1361     /**
1362      * check version code in haps.
1363      *
1364      * @param utility common data
1365      * @param srcFile source file to zip
1366      * @param baseDir current directory name of file
1367      * @return true is for successful and false is for failed
1368      * @throws BundleException FileNotFoundException|IOException.
1369      */
checkVersionInHaps(Utility utility, File srcFile, String baseDir)1370     private boolean checkVersionInHaps(Utility utility, File srcFile, String baseDir) throws BundleException {
1371         try {
1372             String fileStr = srcFile.getName();
1373             if ((fileStr == null) || (fileStr.isEmpty())) {
1374                 throw new BundleException("Compressor::checkVersionInHaps get file name failed");
1375             }
1376             if (!fileStr.toLowerCase(Locale.ENGLISH).endsWith(HAP_SUFFIX)) {
1377                 return true;
1378             }
1379             for (String hapPath : utility.getFormattedHapPathList()) {
1380                 if ((hapPath == null) || (hapPath.isEmpty()) || (!hapPath.contains(baseDir))) {
1381                     continue;
1382                 }
1383                 String versionStr = obtainVersion(srcFile, hapPath);
1384                 String code = obtainInnerVersionCode(versionStr);
1385                 if ((code == null) || (code.isEmpty())) {
1386                     LOG.error("Compressor::checkVersionInHaps version code is null or empty");
1387                     return false;
1388                 }
1389                 if (!versionCode.isEmpty() && !versionCode.equals(code)) {
1390                     LOG.error("Compressor::checkVersionInHaps some haps with different version code");
1391                     return false;
1392                 }
1393                 String name = obtainInnerVersionName(versionStr);
1394                 if ((name == null) || (name.isEmpty())) {
1395                     LOG.error("Compressor::checkVersionInHaps version name is null or empty");
1396                     return false;
1397                 }
1398                 if (!versionName.isEmpty() && !versionName.equals(name)) {
1399                     LOG.error("Compressor::checkVersionInHaps some haps with different version name");
1400                     return false;
1401                 }
1402                 versionCode = code;
1403                 versionName = name;
1404             }
1405         } catch (BundleException exception) {
1406             LOG.error("Compressor::checkVersionInHaps io exception: " + exception.getMessage());
1407             throw new BundleException("Compressor::checkVersionInHaps failed");
1408         }
1409         return true;
1410     }
1411 
1412     /**
1413      * get CRC32 from file.
1414      *
1415      * @param utility common data
1416      * @param file    source file
1417      * @return CRC32
1418      * @throws BundleException FileNotFoundException|IOException.
1419      */
getCrcFromFile(Utility utility, File file)1420     private CRC32 getCrcFromFile(Utility utility, File file) throws BundleException {
1421         FileInputStream fileInputStream = null;
1422         CRC32 crc = new CRC32();
1423         try {
1424             fileInputStream = new FileInputStream(file);
1425             byte[] buffer = new byte[BUFFER_SIZE];
1426 
1427             int count = fileInputStream.read(buffer);
1428             while (count > 0) {
1429                 crc.update(buffer, 0, count);
1430                 count = fileInputStream.read(buffer);
1431             }
1432         } catch (FileNotFoundException ignored) {
1433             LOG.error("Compressor::getCrcFromFile file not found exception");
1434             throw new BundleException("Get Crc from file failed");
1435         } catch (IOException exception) {
1436             LOG.error("Compressor::getCrcFromFile io exception: " + exception.getMessage());
1437             throw new BundleException("Get Crc from file failed");
1438         } finally {
1439             Utility.closeStream(fileInputStream);
1440         }
1441         return crc;
1442     }
1443 
infoSpecialProcess(Utility utility, File srcFile)1444     private void infoSpecialProcess(Utility utility, File srcFile)
1445             throws BundleException {
1446         FileInputStream fileInputStream = null;
1447         BufferedReader bufferedReader = null;
1448         InputStreamReader inputStreamReader = null;
1449 
1450         try {
1451             fileInputStream = new FileInputStream(srcFile);
1452             inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8);
1453             bufferedReader = new BufferedReader(inputStreamReader);
1454             bufferedReader.mark((int) srcFile.length() + 1);
1455             // parse moduleName from pack.info
1456             parsePackModuleName(bufferedReader, utility);
1457             bufferedReader.reset();
1458             parsePackFormName(bufferedReader, utility);
1459             bufferedReader.reset();
1460             parseDeviceType(bufferedReader, utility);
1461             bufferedReader.reset();
1462 
1463             Pattern pattern = Pattern.compile(System.lineSeparator());
1464             String str = bufferedReader.readLine();
1465             StringBuilder builder = new StringBuilder();
1466             while (str != null) {
1467                 Matcher matcher = pattern.matcher(str.trim());
1468                 String dest = matcher.replaceAll("");
1469                 builder.append(dest);
1470                 str = bufferedReader.readLine();
1471             }
1472         } catch (IOException exception) {
1473             LOG.error("Compressor::jsonSpecialProcess io exception: " + exception.getMessage());
1474             throw new BundleException("Json special process failed");
1475         } finally {
1476             Utility.closeStream(bufferedReader);
1477             Utility.closeStream(inputStreamReader);
1478             Utility.closeStream(fileInputStream);
1479         }
1480     }
1481 
1482     /**
1483      * trim and remove "\r\n" in *.json file.
1484      *
1485      * @param utility common data
1486      * @param srcFile file input
1487      * @param entry   zip file entry
1488      * @throws BundleException FileNotFoundException|IOException.
1489      */
jsonSpecialProcess(Utility utility, File srcFile, ZipEntry entry)1490     private void jsonSpecialProcess(Utility utility, File srcFile, ZipEntry entry)
1491             throws BundleException {
1492         FileInputStream fileInputStream = null;
1493         BufferedReader bufferedReader = null;
1494         InputStreamReader inputStreamReader = null;
1495 
1496         try {
1497             fileInputStream = new FileInputStream(srcFile);
1498             inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8);
1499             bufferedReader = new BufferedReader(inputStreamReader);
1500             bufferedReader.mark((int) srcFile.length() + 1);
1501             // parse moduleName from config.json
1502             parseModuleName(bufferedReader, utility);
1503             bufferedReader.reset();
1504             parseCompressNativeLibs(bufferedReader, utility);
1505             bufferedReader.reset();
1506             parseDeviceType(bufferedReader, utility);
1507             bufferedReader.reset();
1508 
1509             Pattern pattern = Pattern.compile(System.lineSeparator());
1510             String str = bufferedReader.readLine();
1511             StringBuilder builder = new StringBuilder();
1512             while (str != null) {
1513                 Matcher matcher = pattern.matcher(str.trim());
1514                 String dest = matcher.replaceAll("");
1515                 builder.append(dest);
1516                 str = bufferedReader.readLine();
1517             }
1518             byte[] trimJson = builder.toString().getBytes(StandardCharsets.UTF_8);
1519 
1520             // update crc
1521             CRC32 crc = new CRC32();
1522             crc.update(trimJson);
1523             entry.setCrc(crc.getValue());
1524 
1525             // update size
1526             entry.setSize(trimJson.length);
1527             entry.setCompressedSize(trimJson.length);
1528 
1529             // update fileTime
1530             FileTime fileTime = FileTime.fromMillis(FILE_TIME);
1531             entry.setLastAccessTime(fileTime);
1532             entry.setLastModifiedTime(fileTime);
1533 
1534             // compress data
1535             zipOut.putNextEntry(entry);
1536             zipOut.write(trimJson);
1537         } catch (IOException exception) {
1538             LOG.error("Compressor::jsonSpecialProcess io exception: " + exception.getMessage());
1539             throw new BundleException("Json special process failed");
1540         } finally {
1541             Utility.closeStream(bufferedReader);
1542             Utility.closeStream(inputStreamReader);
1543             Utility.closeStream(fileInputStream);
1544         }
1545     }
1546 
1547     /**
1548      * get string of config.json from hap file.
1549      *
1550      * @param file    source file
1551      * @param baseDir current directory name of file
1552      * @return string of config.json
1553      * @throws BundleException FileNotFoundException|IOException.
1554      */
obtainVersion(File srcFile, String baseDir)1555     private String obtainVersion(File srcFile, String baseDir) throws BundleException {
1556         ZipFile zipFile = null;
1557         FileInputStream zipInput = null;
1558         InputStream in = null;
1559         ZipInputStream zin = null;
1560         InputStream inputStream = null;
1561         InputStreamReader reader = null;
1562         BufferedReader br = null;
1563         ZipEntry entry = null;
1564         String configJson = "";
1565         try {
1566             zipFile = new ZipFile(srcFile);
1567             zipInput = new FileInputStream(baseDir);
1568             in = new BufferedInputStream(zipInput);
1569             zin = new ZipInputStream(in);
1570             while ((entry = zin.getNextEntry()) != null) {
1571                 if (entry.getName().toLowerCase().equals(CONFIG_JSON)) {
1572                     inputStream = zipFile.getInputStream(entry);
1573                     reader = new InputStreamReader(inputStream);
1574                     br = new BufferedReader(reader);
1575                     if (br != null) {
1576                         configJson = br.readLine();
1577                         break;
1578                     }
1579                 }
1580             }
1581         } catch (IOException exception) {
1582             LOG.error("Compressor::ObtainVersionCode io exception: " + exception.getMessage());
1583             throw new BundleException("Compressor::ObtainVersionCode failed");
1584         } finally {
1585             Utility.closeStream(zipFile);
1586             Utility.closeStream(zipInput);
1587             Utility.closeStream(in);
1588             Utility.closeStream(zin);
1589             Utility.closeStream(inputStream);
1590             Utility.closeStream(reader);
1591             Utility.closeStream(br);
1592         }
1593         return obtainInnerVersion(configJson);
1594     }
1595 
obtainInnerVersion(String configJson)1596     private String obtainInnerVersion(String configJson) throws BundleException {
1597         try {
1598             if (configJson != null) {
1599                 int indexOfVersion = configJson.indexOf(VERSION);
1600                 if (indexOfVersion <= 0) {
1601                     LOG.error("Compressor::obtainInnerVersion obtain index of version failed");
1602                     throw new BundleException("Compressor::obtainInnerVersion obtain index of version failed");
1603                 }
1604                 int lastIndex = configJson.indexOf(JSON_END, indexOfVersion);
1605                 if (lastIndex <= 0) {
1606                     LOG.error("Compressor::obtainInnerVersion obtain last index failed");
1607                     throw new BundleException("Compressor::obtainInnerVersion obtain last index failed");
1608                 }
1609                 String version = configJson.substring(indexOfVersion, lastIndex + 1);
1610                 if (version == null || version.isEmpty()) {
1611                     LOG.error("Compressor::obtainInnerVersion version is null or empty");
1612                     throw new BundleException("Compressor::obtainInnerVersion failed due to null or empty version!");
1613                 }
1614                 return version.trim();
1615             }
1616         } catch (BundleException exception) {
1617             LOG.error("Compressor::obtainInnerVersion io exception: " + exception.getMessage());
1618             throw new BundleException("Compressor::obtainInnerVersion failed");
1619         }
1620         return "";
1621     }
1622 
1623     /**
1624      * get version code from hap file.
1625      *
1626      * @param configJson config.json from hap file
1627      * @return version code
1628      * @throws BundleException FileNotFoundException|IOException.
1629      */
obtainInnerVersionCode(String configJson)1630     private String obtainInnerVersionCode(String configJson) throws BundleException {
1631         try {
1632             if (configJson != null) {
1633                 int indexOfCode = configJson.indexOf(CODE);
1634                 if (indexOfCode <= 0) {
1635                     LOG.error("Compressor::ObtainInnerVersionCode obtain index failed");
1636                     throw new BundleException("Compressor::ObtainInnerVersionCode obtain index failed");
1637                 }
1638                 int index = configJson.indexOf(COLON, indexOfCode);
1639                 if (index <= 0) {
1640                     LOG.error("Compressor::ObtainInnerVersionCode obtain index failed");
1641                     throw new BundleException("Compressor::ObtainInnerVersionCode obtain index failed");
1642                 }
1643                 int lastIndex = configJson.indexOf(COMMA, index);
1644                 if (lastIndex <= 0) {
1645                     LOG.error("Compressor::ObtainInnerVersionCode obtain index failed");
1646                     throw new BundleException("Compressor::ObtainInnerVersionCode obtain index failed");
1647                 }
1648                 String code = configJson.substring(index + 1, lastIndex);
1649                 if (code == null || code.isEmpty()) {
1650                     LOG.error("Compressor::ObtainInnerVersionCode code is null or empty");
1651                     throw new BundleException("Compressor::ObtainInnerVersionCode failed due to null or empty code!");
1652                 }
1653                 return code.trim();
1654             }
1655         } catch (BundleException exception) {
1656             LOG.error("Compressor::ObtainInnerVersionCode io exception: " + exception.getMessage());
1657             throw new BundleException("Compressor::ObtainInnerVersionCode failed");
1658         }
1659         return "";
1660     }
1661 
1662     /**
1663      * get version name from hap file.
1664      *
1665      * @param configJson config.json from hap file
1666      * @return version name
1667      * @throws BundleException FileNotFoundException|IOException.
1668      */
obtainInnerVersionName(String configJson)1669     private String obtainInnerVersionName(String configJson) throws BundleException {
1670         try {
1671             if (configJson != null) {
1672                 int indexOfCode = configJson.indexOf(NAME);
1673                 if (indexOfCode <= 0) {
1674                     LOG.error("Compressor::obtainInnerVersionName obtain index failed");
1675                     throw new BundleException("Compressor::obtainInnerVersionName obtain index failed");
1676                 }
1677                 int index = configJson.indexOf(COLON, indexOfCode);
1678                 if (index <= 0) {
1679                     LOG.error("Compressor::obtainInnerVersionName obtain index failed");
1680                     throw new BundleException("Compressor::obtainInnerVersionName obtain index failed");
1681                 }
1682                 int lastIndex = configJson.indexOf(JSON_END, index);
1683                 if (lastIndex <= 0) {
1684                     LOG.error("Compressor::obtainInnerVersionName obtain index failed");
1685                     throw new BundleException("Compressor::obtainInnerVersionName obtain index failed");
1686                 }
1687                 String name = configJson.substring(index + 1, lastIndex);
1688                 if (name == null || name.isEmpty()) {
1689                     LOG.error("Compressor::obtainInnerVersionName name is null or empty");
1690                     throw new BundleException("Compressor::obtainInnerVersionName failed due to null or empty name!");
1691                 }
1692                 return name.trim();
1693             }
1694         } catch (BundleException exception) {
1695             LOG.error("Compressor::obtainInnerVersionName io exception: " + exception.getMessage());
1696             throw new BundleException("Compressor::obtainInnerVersionName failed");
1697         }
1698         return "";
1699     }
1700 
1701     /**
1702      * Parse module name from config.json
1703      *
1704      * @param bufferedReader config.json buffered Reader
1705      * @param utility        common data
1706      * @throws BundleException IOException
1707      */
parseModuleName(BufferedReader bufferedReader, Utility utility)1708     private void parseModuleName(BufferedReader bufferedReader, Utility utility) throws BundleException {
1709         String lineStr = null;
1710         boolean isDistroStart = false;
1711         try {
1712             while ((lineStr = bufferedReader.readLine()) != null) {
1713                 if (!isDistroStart) {
1714                     if (lineStr.contains(DISTRO)) {
1715                         isDistroStart = true;
1716                     }
1717                     continue;
1718                 }
1719                 if (lineStr.contains(JSON_END)) {
1720                     continue;
1721                 }
1722                 if (lineStr.contains(MODULE_NAME_NEW) || lineStr.contains(MODULE_NAME)) {
1723                     getModuleNameFromString(lineStr, utility);
1724                     break;
1725                 }
1726             }
1727         } catch (IOException exception) {
1728             LOG.error("Compressor::parseModuleName io exception: " + exception.getMessage());
1729             throw new BundleException("Parse module name failed");
1730         }
1731     }
1732 
1733     /**
1734      * Parse module name from pack.info
1735      *
1736      * @param bufferedReader pack.info buffered Reader
1737      * @param utility        common data
1738      * @throws BundleException IOException
1739      */
parsePackModuleName(BufferedReader bufferedReader, Utility utility)1740     private void parsePackModuleName(BufferedReader bufferedReader, Utility utility) throws BundleException {
1741         String lineStr = null;
1742         boolean isDistroStart = false;
1743         try {
1744             while ((lineStr = bufferedReader.readLine()) != null) {
1745                 if (lineStr.contains(DISTRO)) {
1746                     continue;
1747                 }
1748                 if (lineStr.contains(JSON_END)) {
1749                     continue;
1750                 }
1751                 if (lineStr.contains(MODULE_NAME_NEW) || lineStr.contains(MODULE_NAME)) {
1752                     getModuleNameFromString(lineStr, utility);
1753                 }
1754             }
1755         } catch (IOException exception) {
1756             LOG.error("Compressor::parseModuleName io exception: " + exception.getMessage());
1757             throw new BundleException("Parse module name failed");
1758         }
1759     }
1760 
1761     /**
1762      * Parse Forms name from pack.info
1763      *
1764      * @param bufferedReader pack.info buffered Reader
1765      * @param utility        common data
1766      * @throws BundleException IOException
1767      */
parsePackFormName(BufferedReader bufferedReader, Utility utility)1768     private void parsePackFormName(BufferedReader bufferedReader, Utility utility) throws BundleException {
1769         String lineStr = null;
1770         try {
1771             while ((lineStr = bufferedReader.readLine()) != null) {
1772                 if (lineStr.contains("abilities")) {
1773                     continue;
1774                 }
1775                 if (lineStr.contains(FORMS)) {
1776                     continue;
1777                 }
1778                 if (lineStr.contains(JSON_END)) {
1779                     continue;
1780                 }
1781                 if (lineStr.contains(NAME)) {
1782                     getNameFromString(lineStr, utility);
1783                 }
1784             }
1785         } catch (IOException exception) {
1786             LOG.error("Compressor::parseModuleName io exception: " + exception.getMessage());
1787             throw new BundleException("Parse module name failed");
1788         }
1789     }
1790 
1791 
1792     /**
1793      * Get name from line string
1794      *
1795      * @param lineStr line string
1796      * @param utility common data
1797      * @throws BundleException StringIndexOutOfBoundsException
1798      */
getNameFromString(String lineStr, Utility utility)1799     private void getNameFromString(String lineStr, Utility utility) throws BundleException {
1800         try {
1801             int endIndex = lineStr.lastIndexOf(SEMICOLON);
1802             if (endIndex <= 0) {
1803                 LOG.error("Compressor::getModuleNameFromString field the json is not standard.");
1804                 throw new BundleException("Parse module name failed, module-name is invalid");
1805             }
1806             int startIndex = lineStr.lastIndexOf(SEMICOLON, endIndex - 1) + 1;
1807             String formName = lineStr.substring(startIndex, endIndex);
1808             if (formName == null || formName.isEmpty()) {
1809                 LOG.error("Compressor::getModuleNameFromString field module-name is empty");
1810                 throw new BundleException("Parse module name failed, module-name is empty");
1811             }
1812             String[] nameList = formName.split("\\.");
1813             if (nameList.length <= 1) {
1814                 formNamesList.add(formName);
1815                 utility.addFormNameList(formName);
1816             }
1817         } catch (StringIndexOutOfBoundsException exception) {
1818             LOG.error("Compressor::parseModuleName field module-name is fault: " + exception.getMessage());
1819             throw new BundleException("Parse module name failed, module-name is invalid");
1820         }
1821     }
1822 
1823     /**
1824      * Get module name from line string
1825      *
1826      * @param lineStr line string
1827      * @param utility common data
1828      * @throws BundleException StringIndexOutOfBoundsException
1829      */
getModuleNameFromString(String lineStr, Utility utility)1830     private void getModuleNameFromString(String lineStr, Utility utility) throws BundleException {
1831         try {
1832             int endIndex = lineStr.lastIndexOf(SEMICOLON);
1833             if (endIndex <= 0) {
1834                 LOG.error("Compressor::getModuleNameFromString field the json is not standard.");
1835                 throw new BundleException("Parse module name failed, module-name is invalid");
1836             }
1837             int startIndex = lineStr.lastIndexOf(SEMICOLON, endIndex - 1) + 1;
1838             String moduleName = lineStr.substring(startIndex, endIndex);
1839             list.add(moduleName);
1840             if (moduleName == null || moduleName.isEmpty()) {
1841                 LOG.error("Compressor::getModuleNameFromString field module-name is empty");
1842                 throw new BundleException("Parse module name failed, module-name is empty");
1843             }
1844             utility.setModuleName(moduleName);
1845         } catch (StringIndexOutOfBoundsException exception) {
1846             LOG.error("Compressor::parseModuleName field module-name is fault: " + exception.getMessage());
1847             throw new BundleException("Parse module name failed, module-name is invalid");
1848         }
1849     }
1850 
parseCompressNativeLibs(BufferedReader bufferedReader, Utility utility)1851     private void parseCompressNativeLibs(BufferedReader bufferedReader, Utility utility) throws BundleException {
1852         String lineStr = null;
1853         try {
1854             while ((lineStr = bufferedReader.readLine()) != null) {
1855                 if (lineStr.contains(COMPRESS_NATIVE_LIBS)) {
1856                     if (lineStr.contains(Utility.FALSE_STRING)) {
1857                         utility.setIsCompressNativeLibs(false);
1858                         break;
1859                     }
1860                 }
1861             }
1862         } catch (IOException exception) {
1863             LOG.error("Compressor::parseCompressNativeLibs io exception: " + exception.getMessage());
1864             throw new BundleException("Parse compress native libs failed");
1865         }
1866     }
1867 
1868     /**
1869      * ZipOutputStream flush, closeEntry and finish.
1870      */
closeZipOutputStream()1871     private void closeZipOutputStream() {
1872         try {
1873             if (zipOut != null) {
1874                 zipOut.flush();
1875             }
1876         } catch (IOException exception) {
1877             LOG.error("Compressor::closeZipOutputStream flush exception " + exception.getMessage());
1878         }
1879         try {
1880             if (zipOut != null) {
1881                 zipOut.closeEntry();
1882             }
1883         } catch (IOException exception) {
1884             LOG.error("Compressor::closeZipOutputStream close entry io exception " + exception.getMessage());
1885         }
1886         try {
1887             if (zipOut != null) {
1888                 zipOut.finish();
1889             }
1890         } catch (IOException exception) {
1891             LOG.error("Compressor::closeZipOutputStream finish exception " + exception.getMessage());
1892         }
1893     }
1894 
1895     /**
1896      * Parse device type from config.json
1897      *
1898      * @param bufferedReader config.json buffered Reader
1899      * @param utility        common data
1900      * @throws BundleException IOException
1901      */
parseDeviceType(BufferedReader bufferedReader, Utility utility)1902     private void parseDeviceType(BufferedReader bufferedReader, Utility utility) throws BundleException {
1903         String lineStr = null;
1904         boolean isDeviceTypeStart = false;
1905         try {
1906             while ((lineStr = bufferedReader.readLine()) != null) {
1907                 if (!isDeviceTypeStart) {
1908                     if (lineStr.contains(DEVICE_TYPE)) {
1909                         isDeviceTypeStart = true;
1910                     }
1911                     continue;
1912                 }
1913                 if (lineStr.contains(JSON_END)) {
1914                     break;
1915                 }
1916                 utility.setDeviceType(lineStr);
1917                 break;
1918             }
1919         } catch (IOException exception) {
1920             LOG.error("Compressor::parseDeviceType io exception: " + exception.getMessage());
1921             throw new BundleException("Parse device type failed");
1922         }
1923     }
1924 }
1925