• 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.BufferedOutputStream;
20 import java.io.BufferedReader;
21 import java.io.Closeable;
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileOutputStream;
25 import java.io.FileNotFoundException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28 import java.io.IOException;
29 import java.io.OutputStream;
30 import java.security.NoSuchAlgorithmException;
31 import java.util.ArrayList;
32 import java.util.Enumeration;
33 import java.util.HashMap;
34 import java.util.Optional;
35 import java.util.regex.Pattern;
36 import java.util.zip.ZipEntry;
37 import java.util.zip.ZipFile;
38 import java.util.zip.ZipInputStream;
39 import java.security.MessageDigest;
40 
41 /**
42  * file tools
43  *
44  */
45 class FileUtils {
46     private static final int BUFFER_SIZE = 1024;
47     private static final int SHA256_BUFFER_SIZE = 10240;
48     private static final Log LOG = new Log(FileUtils.class.toString());
49     private static final String RESOURCE_PATH = "resources/base/profile/";
50     private static final String SHA256 = "SHA-256";
51     private static final String PATTERN = "[0-9A-Za-z/].{0,4095}";
52 
53     /**
54      * generate fileData byte stream
55      *
56      * @param filePath file path
57      * @return byte array
58      */
getFileData(final String filePath)59     public static byte[] getFileData(final String filePath) {
60         File file = new File(filePath);
61         long fileSize = file.length();
62         byte[] buffer = new byte[(int) fileSize];
63         if (fileSize > Integer.MAX_VALUE) {
64             LOG.error("file too big.");
65             return buffer;
66         }
67         FileInputStream fi = null;
68         try {
69             fi = new FileInputStream(file);
70             int offset = 0;
71             int numRead = 0;
72             while (offset < buffer.length && (numRead = fi.read(buffer, offset, buffer.length - offset)) >= 0) {
73                 offset += numRead;
74             }
75         } catch (IOException exception) {
76             LOG.error("getFileData IOException error: " + exception.getMessage());
77             return new byte[(int) fileSize];
78         } finally {
79             closeStream(fi);
80         }
81         return buffer;
82     }
83 
84     /**
85      * search filePath for special fileName
86      *
87      * @param fileName file name
88      * @param directory dir path
89      * @return filePath
90      */
searchFile(final String fileName, final String directory)91     public static Optional<String> searchFile(final String fileName, final String directory) {
92         ArrayList<String> fileList = new ArrayList<>();
93         getFileList(directory, fileList);
94         for (String fileItem : fileList) {
95             if (fileItem.endsWith(fileName)) {
96                 return Optional.ofNullable(fileItem);
97             }
98         }
99         return Optional.empty();
100     }
101 
102     /**
103      * get file list in filePath
104      *
105      * @param filePath file path
106      * @param fileList file path in arrayList
107      */
getFileList(final String filePath, ArrayList<String> fileList)108     public static void getFileList(final String filePath, ArrayList<String> fileList) {
109         File file = new File(filePath);
110         if (!file.exists()) {
111             LOG.error("getFileList: file is not exists.");
112             return;
113         }
114         File[] files = file.listFiles();
115         if (files == null) {
116             LOG.error("getFileList: no file in this file path.");
117             return;
118         }
119         for (File f : files) {
120             try {
121                 if (f.isFile()) {
122                     fileList.add(f.getCanonicalPath());
123                 } else if (f.isDirectory()) {
124                     getFileList(f.getCanonicalPath(), fileList);
125                 } else {
126                     LOG.error("It's not file or directory.");
127                 }
128             } catch (IOException msg) {
129                 LOG.error("IOException error: " + msg.getMessage());
130                 return;
131             }
132         }
133     }
134 
135     /**
136      * get string from file
137      *
138      * @param filePath file path
139      * @return String for file
140      */
getFileContent(final String filePath)141     public static Optional<String> getFileContent(final String filePath) {
142         if (filePath.isEmpty()) {
143             return Optional.empty();
144         }
145         BufferedReader reader = null;
146         FileInputStream fileInputStream = null;
147         InputStreamReader inputStreamReader = null;
148         StringBuilder content = new StringBuilder();
149         try {
150             fileInputStream = new FileInputStream(filePath);
151             inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
152             reader = new BufferedReader(inputStreamReader);
153             String tempString;
154             while ((tempString = reader.readLine()) != null) {
155                 content.append(tempString);
156             }
157         } catch (IOException msg) {
158             LOG.error(PackingToolErrMsg.GET_FILE_CONTENT_FAILED.toString(
159                     "IOException: " + msg.getMessage()));
160             return Optional.empty();
161         } finally {
162             closeStream(reader);
163             closeStream(inputStreamReader);
164             closeStream(fileInputStream);
165         }
166         return Optional.ofNullable(content.toString());
167     }
168 
169     /**
170      * close file stream
171      *
172      * @param fileStream file stream
173      */
closeStream(Closeable fileStream)174     public static void closeStream(Closeable fileStream) {
175         try {
176             if (fileStream != null) {
177                 fileStream.close();
178             }
179         } catch (IOException msg) {
180             LOG.error(PackingToolErrMsg.CLOSE_STREAM_EXCEPTION.toString(
181                     "Close stream exist IOException: " + msg.getMessage()));
182         }
183     }
184 
185     /**
186      * delete file
187      *
188      * @param path file path which will be deleted
189      */
deleteFile(final String path)190     public static void deleteFile(final String path) {
191         File file = new File(path);
192         if (file.exists()) {
193             file.delete();
194         }
195     }
196 
197     /**
198      * unzip hap package to path
199      *
200      * @param hapPath zip file
201      * @param destDir path after unzip file
202      */
unzip(final String hapPath, final String destDir)203     public static void unzip(final String hapPath, final String destDir) {
204         File file = new File(destDir);
205         if (!file.exists()) {
206             file.mkdirs();
207         }
208 
209         ZipFile zipFile = null;
210         BufferedInputStream bis = null;
211         BufferedOutputStream bos = null;
212         FileOutputStream fos = null;
213         try {
214             zipFile = new ZipFile(hapPath);
215             Enumeration<? extends ZipEntry> entries = zipFile.entries();
216             int entriesNum = 0;
217             while (entries.hasMoreElements()) {
218                 entriesNum++;
219                 ZipEntry entry = entries.nextElement();
220                 if (entry == null) {
221                     continue;
222                 }
223                 String filePath = destDir + File.separator + entry.getName();
224                 if (!matchPattern(filePath)) {
225                     LOG.error("Input invalid file: " + filePath);
226                     throw new BundleException("Input invalid file " + filePath);
227                 }
228                 if (entry.isDirectory()) {
229                     new File(filePath).mkdirs();
230                     continue;
231                 }
232 
233                 bis = new BufferedInputStream(zipFile.getInputStream(entry));
234                 File newFile = new File(filePath);
235                 File parent = newFile.getParentFile();
236                 if (parent != null && (!parent.exists())) {
237                     parent.mkdirs();
238                 }
239 
240                 fos = new FileOutputStream(newFile);
241                 bos = new BufferedOutputStream(fos, BUFFER_SIZE);
242 
243                 int count;
244                 int total = 0;
245                 byte[] data = new byte[BUFFER_SIZE];
246                 while ((count = bis.read(data, 0, BUFFER_SIZE)) != -1) {
247                     bos.write(data, 0, count);
248                     total += count;
249                 }
250 
251                 bos.flush();
252                 bos.close();
253                 fos.close();
254                 bis.close();
255             }
256         } catch (IOException | BundleException exception) {
257             LOG.error("unzip file failed " + exception.getMessage());
258         } finally {
259             closeStream(bos);
260             closeStream(fos);
261             closeStream(bis);
262             closeStream(zipFile);
263         }
264     }
265 
266     /**
267      * delete directory
268      *
269      * @param directory dir path which will be deleted
270      */
deleteDirectory(final String directory)271     public static void deleteDirectory(final String directory) {
272         File dir = new File(directory);
273         if (!dir.exists()) {
274             return;
275         }
276 
277         File[] fileList = dir.listFiles();
278         if (fileList == null) {
279             return;
280         }
281         for (File file : fileList) {
282             try {
283                 if (file.isFile()) {
284                     file.delete();
285                 } else if (file.isDirectory()) {
286                     deleteDirectory(file.getCanonicalPath());
287                 } else {
288                     LOG.error("It's not file or directory.");
289                 }
290             } catch (IOException msg) {
291                 LOG.error("deleteDirectory IOException : " + msg.getMessage());
292             }
293         }
294         dir.delete();
295     }
296 
297     /**
298      * format filepath
299      *
300      * @param filePath file path which is need to format
301      * @return canonicalPath for filePath
302      */
getFormatedPath(final String filePath)303     public static Optional<String> getFormatedPath(final String filePath) {
304         String absPath;
305         try {
306             File file = new File(filePath);
307             absPath = file.getCanonicalPath();
308         } catch (IOException msg) {
309             LOG.error("format path IOException : " + msg.getMessage());
310             return Optional.empty();
311         }
312         return Optional.of(absPath);
313     }
314 
315     /**
316      * check file whether is exist or not
317      *
318      * @param filePath bin file path
319      * @return true: file is exist, false: file is not exist
320      */
checkFileIsExists(final String filePath)321     public static boolean checkFileIsExists(final String filePath) {
322         if (filePath.isEmpty()) {
323             return false;
324         }
325 
326         Optional<String> absFilePath = getFormatedPath(filePath);
327         if (!absFilePath.isPresent()) {
328             return false;
329         }
330 
331         File file = new File(absFilePath.get());
332         if (!file.exists()) {
333             return false;
334         }
335         return true;
336     }
337 
338     /**
339      * copy a file to another place.
340      *
341      * @param sourceFile is the source file
342      * @param destFile is the destination file
343      * @throws IOException FileNotFoundException|IOException.
344      */
copyFile(File sourceFile, File destFile)345     public static void copyFile(File sourceFile, File destFile) throws IOException, BundleException {
346         if (sourceFile == null || destFile == null) {
347             String errMsg = "Source file or destination file is null.";
348             LOG.error(PackingToolErrMsg.COPY_FILE_FAILED.toString(errMsg));
349             throw new BundleException(errMsg);
350         }
351         InputStream inputStream = null;
352         OutputStream outputStream = null;
353         try {
354             inputStream = new FileInputStream(sourceFile);
355             outputStream = new FileOutputStream(destFile);
356             byte[] buffer = new byte[BUFFER_SIZE];
357             int length;
358             while ((length = inputStream.read(buffer)) > 0) {
359                 outputStream.write(buffer, 0, length);
360             }
361         } finally {
362             Utility.closeStream(inputStream);
363             Utility.closeStream(outputStream);
364         }
365     }
366 
367     /**
368      * make a directory if not exist.
369      *
370      * @param dirFile is the directory file
371      * @throws IOException FileNotFoundException|IOException.
372      */
makeDir(File dirFile)373     public static void makeDir(File dirFile) throws IOException, BundleException {
374         if (dirFile == null) {
375             String errMsg = "Input file is null.";
376             LOG.error(PackingToolErrMsg.MAKE_DIR_FAILED.toString(errMsg));
377             throw new BundleException(errMsg);
378         }
379         dirFile.mkdirs();
380     }
381 
382     /**
383      * check json type code in haps.
384      *
385      * @param srcFile source file to zip
386      * @return true is for successful and false is for failed
387      * @throws BundleException FileNotFoundException|IOException.
388      */
getJsonInZips(File srcFile, String jsonName)389     public static String getJsonInZips(File srcFile, String jsonName) throws BundleException {
390         String fileStr = srcFile.getPath();
391         ZipFile zipFile = null;
392         FileInputStream zipInput = null;
393         ZipInputStream zin = null;
394         InputStream inputStream = null;
395         InputStreamReader reader = null;
396         BufferedReader br = null;
397         ZipEntry entry = null;
398         StringBuilder jsonStr = new StringBuilder();
399         try {
400             zipFile = new ZipFile(srcFile);
401             zipInput = new FileInputStream(fileStr);
402             zin = new ZipInputStream(zipInput);
403             while ((entry = zin.getNextEntry()) != null) {
404                 if (entry.getName().toLowerCase().equals(jsonName)) {
405                     inputStream = zipFile.getInputStream(entry);
406                     reader = new InputStreamReader(inputStream);
407                     br = new BufferedReader(reader);
408                     String line;
409                     while ((line = br.readLine()) != null) {
410                         jsonStr.append(line);
411                     }
412                     inputStream.close();
413                 }
414             }
415             jsonStr = new StringBuilder(jsonStr.toString().replaceAll("\r|\n|\t", ""));
416         } catch (IOException exception) {
417             LOG.error(PackingToolErrMsg.IO_EXCEPTION.toString(
418                 "Get Json in zips exist IOException: " + exception.getMessage()));
419             throw new BundleException("Compressor::checkModuleTypeInHaps failed.");
420         } finally {
421             Utility.closeStream(zipFile);
422             Utility.closeStream(zipInput);
423             Utility.closeStream(zin);
424             Utility.closeStream(inputStream);
425             Utility.closeStream(reader);
426             Utility.closeStream(br);
427         }
428         return jsonStr.toString();
429     }
430 
431     /**
432      * get all resource file in profile.
433      *
434      * @param zipFile is the hap file
435      * @throws BundleException when get profile json file failed
436      */
getProfileJson(ZipFile zipFile)437     static HashMap<String, String> getProfileJson(ZipFile zipFile) throws BundleException {
438         HashMap<String, String> resourceMap = new HashMap<>();
439         try {
440             final Enumeration<? extends ZipEntry> entries = zipFile.entries();
441             while (entries.hasMoreElements()) {
442                 final ZipEntry entry = entries.nextElement();
443                 if (entry.getName().contains(RESOURCE_PATH)) {
444                     String filePath = entry.getName();
445                     String fileName = filePath.replaceAll(RESOURCE_PATH, "");
446                     String fileContent = getFileStringFromZip(filePath, zipFile);
447                     resourceMap.put(fileName, fileContent);
448                 }
449             }
450         } catch (IOException e) {
451             LOG.error(PackingToolErrMsg.IO_EXCEPTION.toString(
452                 "Get profile json exist IOException: " + e.getMessage()));
453             throw new BundleException("Get profile json failed.");
454         }
455         return resourceMap;
456     }
457 
458     /**
459      * get file content in string from zip
460      *
461      * @param fileName is the file name we want to read
462      * @param zipFile is the zip file
463      */
getFileStringFromZip(String fileName, ZipFile zipFile)464     public static String getFileStringFromZip(String fileName, ZipFile zipFile)
465             throws IOException {
466         ZipEntry entry = zipFile.getEntry(fileName);
467         if (entry == null) {
468             LOG.debug("Uncompress::readStringFromFile " + fileName + " not found exception.");
469             return "";
470         }
471         InputStream fileInputStream = null;
472         BufferedReader bufferedReader = null;
473         try {
474             fileInputStream = zipFile.getInputStream(entry);
475             bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream, "UTF-8"));
476             String line;
477             StringBuilder sb = new StringBuilder();
478             while ((line = bufferedReader.readLine()) != null) {
479                 sb.append(line);
480             }
481             return sb.toString();
482         } finally {
483             Utility.closeStream(bufferedReader);
484             Utility.closeStream(fileInputStream);
485         }
486     }
487 
488     /**
489      * get sha-256 for file
490      *
491      * @param hapPath is the input path of file
492      */
getSha256(String hapPath)493     public static String getSha256(String hapPath) {
494         String sha256 = "";
495         BufferedInputStream inputStream = null;
496         try {
497             File file = new File(hapPath);
498             inputStream = new BufferedInputStream(new FileInputStream(file));
499             byte[] buffer = new byte[SHA256_BUFFER_SIZE];
500             MessageDigest md5 = MessageDigest.getInstance(SHA256);
501             int size = -1;
502             while ((size = inputStream.read(buffer)) != -1) {
503                 md5.update(buffer, 0, size);
504             }
505             sha256 = toHex(md5.digest());
506         } catch (FileNotFoundException e) {
507             LOG.error("input hap file is not found: " + e.getMessage());
508         } catch (NoSuchAlgorithmException e) {
509             LOG.error("can not provide sha-256 algorithm: " + e.getMessage());
510         } catch (IOException e) {
511             LOG.error("input hap IO exception: " + e.getMessage());
512         } finally {
513             Utility.closeStream(inputStream);
514         }
515         return sha256;
516     }
517 
toHex(byte[] data)518     private static String toHex(byte[] data) {
519         StringBuilder hexString = new StringBuilder();
520         for (byte item : data) {
521             hexString.append(Integer.toHexString(item & 0xFF));
522         }
523         return hexString.toString();
524     }
525 
526     /**
527      * unzip file
528      *
529      * @param zipFilePath is the zipFilePath
530      * @param destDirPath is the output dest path
531      */
unzipFile(String zipFilePath, String destDirPath)532     public static boolean unzipFile(String zipFilePath, String destDirPath) {
533         boolean success = false;
534         File destDir = new File(destDirPath);
535         if (!destDir.exists()) {
536             destDir.mkdirs();
537         }
538         ZipInputStream zipInputStream = null;
539         try {
540             zipInputStream = new ZipInputStream(new FileInputStream(zipFilePath));
541             ZipEntry entry = zipInputStream.getNextEntry();
542             while (entry != null) {
543                 String filePath = destDirPath + File.separator + entry.getName();
544                 if (!matchPattern(filePath)) {
545                     LOG.error("Input invalid file " + filePath + ".");
546                     return false;
547                 }
548                 if (!entry.isDirectory()) {
549                     extractFile(zipInputStream, filePath);
550                 } else {
551                     File dir = new File(filePath);
552                     dir.mkdirs();
553                 }
554                 zipInputStream.closeEntry();
555                 entry = zipInputStream.getNextEntry();
556             }
557             success = true;
558         } catch (IOException e) {
559             LOG.error("FileUtil::unzipFile failed, IOException is " + e.getMessage());
560         } finally {
561             Utility.closeStream(zipInputStream);
562         }
563         return success;
564     }
565 
extractFile(ZipInputStream zipInputStream, String filePath)566     private static void extractFile(ZipInputStream zipInputStream, String filePath) {
567         BufferedOutputStream bufferedOutputStream = null;
568         try {
569             if (!matchPattern(filePath)) {
570                 LOG.error("input invalid file: " + filePath);
571                 throw new BundleException("input invalid file " + filePath + ".");
572             }
573             bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(filePath));
574             byte[] bytes = new byte[BUFFER_SIZE];
575             int readLength = 0;
576             while ((readLength = zipInputStream.read(bytes)) != -1) {
577                 bufferedOutputStream.write(bytes, 0, readLength);
578             }
579         } catch (IOException | BundleException e) {
580             LOG.error("FileUtil::extractFile failed, Exception is " + e.getMessage());
581         } finally {
582             Utility.closeStream(bufferedOutputStream);
583         }
584     }
585 
matchPattern(String path)586     static boolean matchPattern(String path) {
587         if (!Pattern.matches(PATTERN, path)) {
588             LOG.error("input invalid file of " + path + ".");
589             return false;
590         }
591         return true;
592     }
593 
594     /**
595      * getFileSize
596      *
597      * @param filePath is the input file path
598      * @return file length
599      */
getFileSize(String filePath)600     public static long getFileSize(String filePath) {
601         File file = new File(filePath);
602         if (file.exists() && file.isFile()) {
603             return file.length();
604         }
605         String errMsg = "input " + filePath + " is not a valid file.";
606         LOG.error(PackingToolErrMsg.GET_FILE_SIZE_FAILED.toString(errMsg));
607         return 0;
608     }
609 
610     /**
611      * Create a parent directory for a file
612      *
613      * @param file file
614      */
createParentDir(File file)615     public static void createParentDir(File file) {
616         if (file != null && file.getParentFile() != null && !file.getParentFile().exists()) {
617             file.getParentFile().mkdirs();
618         }
619     }
620 
621     /**
622      * copy Stream
623      *
624      * @param inputStream input stream
625      * @param outputStream out stream
626      * @throws IOException IOException.
627      */
copyStream(InputStream inputStream, OutputStream outputStream)628     public static void copyStream(InputStream inputStream, OutputStream outputStream) throws IOException {
629         byte[] buffer = new byte[BUFFER_SIZE];
630         int bytesRead = 0;
631         while ((bytesRead = inputStream.read(buffer)) != -1) {
632             outputStream.write(buffer, 0, bytesRead);
633         }
634     }
635 }
636