• 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("get file content fail, msg is " + msg.getMessage());
159             return Optional.empty();
160         } finally {
161             closeStream(reader);
162             closeStream(inputStreamReader);
163             closeStream(fileInputStream);
164         }
165         return Optional.ofNullable(content.toString());
166     }
167 
168     /**
169      * close file stream
170      *
171      * @param fileStream file stream
172      */
closeStream(Closeable fileStream)173     public static void closeStream(Closeable fileStream) {
174         try {
175             if (fileStream != null) {
176                 fileStream.close();
177             }
178         } catch (IOException msg) {
179             LOG.error("stream close Error, msg is " + msg.getMessage());
180         }
181     }
182 
183     /**
184      * delete file
185      *
186      * @param path file path which will be deleted
187      */
deleteFile(final String path)188     public static void deleteFile(final String path) {
189         File file = new File(path);
190         if (file.exists()) {
191             file.delete();
192         }
193     }
194 
195     /**
196      * unzip hap package to path
197      *
198      * @param hapPath zip file
199      * @param destDir path after unzip file
200      */
unzip(final String hapPath, final String destDir)201     public static void unzip(final String hapPath, final String destDir) {
202         File file = new File(destDir);
203         if (!file.exists()) {
204             file.mkdirs();
205         }
206 
207         ZipFile zipFile = null;
208         BufferedInputStream bis = null;
209         BufferedOutputStream bos = null;
210         FileOutputStream fos = null;
211         try {
212             zipFile = new ZipFile(hapPath);
213             Enumeration<? extends ZipEntry> entries = zipFile.entries();
214             int entriesNum = 0;
215             while (entries.hasMoreElements()) {
216                 entriesNum++;
217                 ZipEntry entry = entries.nextElement();
218                 if (entry == null) {
219                     continue;
220                 }
221                 String filePath = destDir + File.separator + entry.getName();
222                 if (!matchPattern(filePath)) {
223                     LOG.error("Input invalid file: " + filePath);
224                     throw new BundleException("Input invalid file " + filePath);
225                 }
226                 if (entry.isDirectory()) {
227                     new File(filePath).mkdirs();
228                     continue;
229                 }
230 
231                 bis = new BufferedInputStream(zipFile.getInputStream(entry));
232                 File newFile = new File(filePath);
233                 File parent = newFile.getParentFile();
234                 if (parent != null && (!parent.exists())) {
235                     parent.mkdirs();
236                 }
237 
238                 fos = new FileOutputStream(newFile);
239                 bos = new BufferedOutputStream(fos, BUFFER_SIZE);
240 
241                 int count;
242                 int total = 0;
243                 byte[] data = new byte[BUFFER_SIZE];
244                 while ((count = bis.read(data, 0, BUFFER_SIZE)) != -1) {
245                     bos.write(data, 0, count);
246                     total += count;
247                 }
248 
249                 bos.flush();
250                 bos.close();
251                 fos.close();
252                 bis.close();
253             }
254         } catch (IOException | BundleException exception) {
255             LOG.error("unzip file failed " + exception.getMessage());
256         } finally {
257             closeStream(bos);
258             closeStream(fos);
259             closeStream(bis);
260             closeStream(zipFile);
261         }
262     }
263 
264     /**
265      * delete directory
266      *
267      * @param directory dir path which will be deleted
268      */
deleteDirectory(final String directory)269     public static void deleteDirectory(final String directory) {
270         File dir = new File(directory);
271         if (!dir.exists()) {
272             return;
273         }
274 
275         File[] fileList = dir.listFiles();
276         if (fileList == null) {
277             return;
278         }
279         for (File file : fileList) {
280             try {
281                 if (file.isFile()) {
282                     file.delete();
283                 } else if (file.isDirectory()) {
284                     deleteDirectory(file.getCanonicalPath());
285                 } else {
286                     LOG.error("It's not file or directory.");
287                 }
288             } catch (IOException msg) {
289                 LOG.error("deleteDirectory IOException : " + msg.getMessage());
290             }
291         }
292         dir.delete();
293     }
294 
295     /**
296      * format filepath
297      *
298      * @param filePath file path which is need to format
299      * @return canonicalPath for filePath
300      */
getFormatedPath(final String filePath)301     public static Optional<String> getFormatedPath(final String filePath) {
302         String absPath;
303         try {
304             File file = new File(filePath);
305             absPath = file.getCanonicalPath();
306         } catch (IOException msg) {
307             LOG.error("format path IOException : " + msg.getMessage());
308             return Optional.empty();
309         }
310         return Optional.of(absPath);
311     }
312 
313     /**
314      * check file whether is exist or not
315      *
316      * @param filePath bin file path
317      * @return true: file is exist, false: file is not exist
318      */
checkFileIsExists(final String filePath)319     public static boolean checkFileIsExists(final String filePath) {
320         if (filePath.isEmpty()) {
321             return false;
322         }
323 
324         Optional<String> absFilePath = getFormatedPath(filePath);
325         if (!absFilePath.isPresent()) {
326             return false;
327         }
328 
329         File file = new File(absFilePath.get());
330         if (!file.exists()) {
331             return false;
332         }
333         return true;
334     }
335 
336     /**
337      * copy a file to another place.
338      *
339      * @param sourceFile is the source file
340      * @param destFile is the destination file
341      * @throws IOException FileNotFoundException|IOException.
342      */
copyFile(File sourceFile, File destFile)343     public static void copyFile(File sourceFile, File destFile) throws IOException, BundleException {
344         if (sourceFile == null || destFile == null) {
345             String errMsg = "CompressorFileUtil::copyFile input file is null.";
346             LOG.error(errMsg);
347             throw new BundleException(errMsg);
348         }
349         InputStream inputStream = null;
350         OutputStream outputStream = null;
351         try {
352             inputStream = new FileInputStream(sourceFile);
353             outputStream = new FileOutputStream(destFile);
354             byte[] buffer = new byte[BUFFER_SIZE];
355             int length;
356             while ((length = inputStream.read(buffer)) > 0) {
357                 outputStream.write(buffer, 0, length);
358             }
359         } finally {
360             Utility.closeStream(inputStream);
361             Utility.closeStream(outputStream);
362         }
363     }
364 
365     /**
366      * make a directory if not exist.
367      *
368      * @param dirFile is the directory file
369      * @throws IOException FileNotFoundException|IOException.
370      */
makeDir(File dirFile)371     public static void makeDir(File dirFile) throws IOException, BundleException {
372         if (dirFile == null) {
373             String errMsg = "CompressorFileUtil::makeDir input file is null.";
374             LOG.error(errMsg);
375             throw new BundleException(errMsg);
376         }
377         dirFile.mkdirs();
378     }
379 
380     /**
381      * check json type code in haps.
382      *
383      * @param srcFile source file to zip
384      * @return true is for successful and false is for failed
385      * @throws BundleException FileNotFoundException|IOException.
386      */
getJsonInZips(File srcFile, String jsonName)387     public static String getJsonInZips(File srcFile, String jsonName) throws BundleException {
388         String fileStr = srcFile.getPath();
389         ZipFile zipFile = null;
390         FileInputStream zipInput = null;
391         ZipInputStream zin = null;
392         InputStream inputStream = null;
393         InputStreamReader reader = null;
394         BufferedReader br = null;
395         ZipEntry entry = null;
396         StringBuilder jsonStr = new StringBuilder();
397         try {
398             zipFile = new ZipFile(srcFile);
399             zipInput = new FileInputStream(fileStr);
400             zin = new ZipInputStream(zipInput);
401             while ((entry = zin.getNextEntry()) != null) {
402                 if (entry.getName().toLowerCase().equals(jsonName)) {
403                     inputStream = zipFile.getInputStream(entry);
404                     reader = new InputStreamReader(inputStream);
405                     br = new BufferedReader(reader);
406                     String line;
407                     while ((line = br.readLine()) != null) {
408                         jsonStr.append(line);
409                     }
410                     inputStream.close();
411                 }
412             }
413             jsonStr = new StringBuilder(jsonStr.toString().replaceAll("\r|\n|\t", ""));
414         } catch (IOException exception) {
415             LOG.error("Compressor::checkModuleTypeInHaps io exception: " + exception.getMessage());
416             throw new BundleException("Compressor::checkModuleTypeInHaps failed.");
417         } finally {
418             Utility.closeStream(zipFile);
419             Utility.closeStream(zipInput);
420             Utility.closeStream(zin);
421             Utility.closeStream(inputStream);
422             Utility.closeStream(reader);
423             Utility.closeStream(br);
424         }
425         return jsonStr.toString();
426     }
427 
428     /**
429      * get all resource file in profile.
430      *
431      * @param zipFile is the hap file
432      * @throws BundleException when get profile json file failed
433      */
getProfileJson(ZipFile zipFile)434     static HashMap<String, String> getProfileJson(ZipFile zipFile) throws BundleException {
435         HashMap<String, String> resourceMap = new HashMap<>();
436         try {
437             final Enumeration<? extends ZipEntry> entries = zipFile.entries();
438             while (entries.hasMoreElements()) {
439                 final ZipEntry entry = entries.nextElement();
440                 if (entry.getName().contains(RESOURCE_PATH)) {
441                     String filePath = entry.getName();
442                     String fileName = filePath.replaceAll(RESOURCE_PATH, "");
443                     String fileContent = getFileStringFromZip(filePath, zipFile);
444                     resourceMap.put(fileName, fileContent);
445                 }
446             }
447         } catch (IOException e) {
448             LOG.error("FileUtil::getProfileJson IOException: " + e.getMessage());
449             throw new BundleException("FileUtil::getProfileJson failed.");
450         }
451         return resourceMap;
452     }
453 
454     /**
455      * get file content in string from zip
456      *
457      * @param fileName is the file name we want to read
458      * @param zipFile is the zip file
459      */
getFileStringFromZip(String fileName, ZipFile zipFile)460     public static String getFileStringFromZip(String fileName, ZipFile zipFile)
461             throws IOException {
462         ZipEntry entry = zipFile.getEntry(fileName);
463         if (entry == null) {
464             LOG.debug("Uncompress::readStringFromFile " + fileName + " not found exception.");
465             return "";
466         }
467         InputStream fileInputStream = null;
468         BufferedReader bufferedReader = null;
469         try {
470             fileInputStream = zipFile.getInputStream(entry);
471             bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream, "UTF-8"));
472             String line;
473             StringBuilder sb = new StringBuilder();
474             while ((line = bufferedReader.readLine()) != null) {
475                 sb.append(line);
476             }
477             return sb.toString();
478         } finally {
479             Utility.closeStream(bufferedReader);
480             Utility.closeStream(fileInputStream);
481         }
482     }
483 
484     /**
485      * get sha-256 for file
486      *
487      * @param hapPath is the input path of file
488      */
getSha256(String hapPath)489     public static String getSha256(String hapPath) {
490         String sha256 = "";
491         BufferedInputStream inputStream = null;
492         try {
493             File file = new File(hapPath);
494             inputStream = new BufferedInputStream(new FileInputStream(file));
495             byte[] buffer = new byte[SHA256_BUFFER_SIZE];
496             MessageDigest md5 = MessageDigest.getInstance(SHA256);
497             int size = -1;
498             while ((size = inputStream.read(buffer)) != -1) {
499                 md5.update(buffer, 0, size);
500             }
501             sha256 = toHex(md5.digest());
502         } catch (FileNotFoundException e) {
503             LOG.error("input hap file is not found: " + e.getMessage());
504         } catch (NoSuchAlgorithmException e) {
505             LOG.error("can not provide sha-256 algorithm: " + e.getMessage());
506         } catch (IOException e) {
507             LOG.error("input hap IO exception: " + e.getMessage());
508         } finally {
509             Utility.closeStream(inputStream);
510         }
511         return sha256;
512     }
513 
toHex(byte[] data)514     private static String toHex(byte[] data) {
515         StringBuilder hexString = new StringBuilder();
516         for (byte item : data) {
517             hexString.append(Integer.toHexString(item & 0xFF));
518         }
519         return hexString.toString();
520     }
521 
522     /**
523      * unzip file
524      *
525      * @param zipFilePath is the zipFilePath
526      * @param destDirPath is the output dest path
527      */
unzipFile(String zipFilePath, String destDirPath)528     public static boolean unzipFile(String zipFilePath, String destDirPath) {
529         boolean success = false;
530         File destDir = new File(destDirPath);
531         if (!destDir.exists()) {
532             destDir.mkdirs();
533         }
534         ZipInputStream zipInputStream = null;
535         try {
536             zipInputStream = new ZipInputStream(new FileInputStream(zipFilePath));
537             ZipEntry entry = zipInputStream.getNextEntry();
538             while (entry != null) {
539                 String filePath = destDirPath + File.separator + entry.getName();
540                 if (!matchPattern(filePath)) {
541                     LOG.error("Input invalid file " + filePath + ".");
542                     return false;
543                 }
544                 if (!entry.isDirectory()) {
545                     extractFile(zipInputStream, filePath);
546                 } else {
547                     File dir = new File(filePath);
548                     dir.mkdirs();
549                 }
550                 zipInputStream.closeEntry();
551                 entry = zipInputStream.getNextEntry();
552             }
553             success = true;
554         } catch (IOException e) {
555             LOG.error("FileUtil::unzipFile failed, IOException is " + e.getMessage());
556         } finally {
557             Utility.closeStream(zipInputStream);
558         }
559         return success;
560     }
561 
extractFile(ZipInputStream zipInputStream, String filePath)562     private static void extractFile(ZipInputStream zipInputStream, String filePath) {
563         BufferedOutputStream bufferedOutputStream = null;
564         try {
565             if (!matchPattern(filePath)) {
566                 LOG.error("input invalid file: " + filePath);
567                 throw new BundleException("input invalid file " + filePath + ".");
568             }
569             bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(filePath));
570             byte[] bytes = new byte[BUFFER_SIZE];
571             int readLength = 0;
572             while ((readLength = zipInputStream.read(bytes)) != -1) {
573                 bufferedOutputStream.write(bytes, 0, readLength);
574             }
575         } catch (IOException | BundleException e) {
576             LOG.error("FileUtil::extractFile failed, Exception is " + e.getMessage());
577         } finally {
578             Utility.closeStream(bufferedOutputStream);
579         }
580     }
581 
matchPattern(String path)582     static boolean matchPattern(String path) {
583         if (!Pattern.matches(PATTERN, path)) {
584             LOG.error("input invalid file of " + path + ".");
585             return false;
586         }
587         return true;
588     }
589 
590     /**
591      * getFileSize
592      *
593      * @param filePath is the input file path
594      * @return file length
595      */
getFileSize(String filePath)596     public static long getFileSize(String filePath) {
597         File file = new File(filePath);
598         if (file.exists() && file.isFile()) {
599             return file.length();
600         }
601         LOG.error("input " + filePath + " is not a valid file.");
602         return 0;
603     }
604 }
605