• 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 = "CompressorFileUtil::copyFile input file is null.";
348             LOG.error(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 = "CompressorFileUtil::makeDir input file is null.";
376             LOG.error(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("Compressor::checkModuleTypeInHaps io exception: " + exception.getMessage());
418             throw new BundleException("Compressor::checkModuleTypeInHaps failed.");
419         } finally {
420             Utility.closeStream(zipFile);
421             Utility.closeStream(zipInput);
422             Utility.closeStream(zin);
423             Utility.closeStream(inputStream);
424             Utility.closeStream(reader);
425             Utility.closeStream(br);
426         }
427         return jsonStr.toString();
428     }
429 
430     /**
431      * get all resource file in profile.
432      *
433      * @param zipFile is the hap file
434      * @throws BundleException when get profile json file failed
435      */
getProfileJson(ZipFile zipFile)436     static HashMap<String, String> getProfileJson(ZipFile zipFile) throws BundleException {
437         HashMap<String, String> resourceMap = new HashMap<>();
438         try {
439             final Enumeration<? extends ZipEntry> entries = zipFile.entries();
440             while (entries.hasMoreElements()) {
441                 final ZipEntry entry = entries.nextElement();
442                 if (entry.getName().contains(RESOURCE_PATH)) {
443                     String filePath = entry.getName();
444                     String fileName = filePath.replaceAll(RESOURCE_PATH, "");
445                     String fileContent = getFileStringFromZip(filePath, zipFile);
446                     resourceMap.put(fileName, fileContent);
447                 }
448             }
449         } catch (IOException e) {
450             LOG.error(PackingToolErrMsg.IO_EXCEPTION.toString("Get profile json exist IOExpection: " + e.getMessage()));
451             throw new BundleException("Get profile json failed.");
452         }
453         return resourceMap;
454     }
455 
456     /**
457      * get file content in string from zip
458      *
459      * @param fileName is the file name we want to read
460      * @param zipFile is the zip file
461      */
getFileStringFromZip(String fileName, ZipFile zipFile)462     public static String getFileStringFromZip(String fileName, ZipFile zipFile)
463             throws IOException {
464         ZipEntry entry = zipFile.getEntry(fileName);
465         if (entry == null) {
466             LOG.debug("Uncompress::readStringFromFile " + fileName + " not found exception.");
467             return "";
468         }
469         InputStream fileInputStream = null;
470         BufferedReader bufferedReader = null;
471         try {
472             fileInputStream = zipFile.getInputStream(entry);
473             bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream, "UTF-8"));
474             String line;
475             StringBuilder sb = new StringBuilder();
476             while ((line = bufferedReader.readLine()) != null) {
477                 sb.append(line);
478             }
479             return sb.toString();
480         } finally {
481             Utility.closeStream(bufferedReader);
482             Utility.closeStream(fileInputStream);
483         }
484     }
485 
486     /**
487      * get sha-256 for file
488      *
489      * @param hapPath is the input path of file
490      */
getSha256(String hapPath)491     public static String getSha256(String hapPath) {
492         String sha256 = "";
493         BufferedInputStream inputStream = null;
494         try {
495             File file = new File(hapPath);
496             inputStream = new BufferedInputStream(new FileInputStream(file));
497             byte[] buffer = new byte[SHA256_BUFFER_SIZE];
498             MessageDigest md5 = MessageDigest.getInstance(SHA256);
499             int size = -1;
500             while ((size = inputStream.read(buffer)) != -1) {
501                 md5.update(buffer, 0, size);
502             }
503             sha256 = toHex(md5.digest());
504         } catch (FileNotFoundException e) {
505             LOG.error("input hap file is not found: " + e.getMessage());
506         } catch (NoSuchAlgorithmException e) {
507             LOG.error("can not provide sha-256 algorithm: " + e.getMessage());
508         } catch (IOException e) {
509             LOG.error("input hap IO exception: " + e.getMessage());
510         } finally {
511             Utility.closeStream(inputStream);
512         }
513         return sha256;
514     }
515 
toHex(byte[] data)516     private static String toHex(byte[] data) {
517         StringBuilder hexString = new StringBuilder();
518         for (byte item : data) {
519             hexString.append(Integer.toHexString(item & 0xFF));
520         }
521         return hexString.toString();
522     }
523 
524     /**
525      * unzip file
526      *
527      * @param zipFilePath is the zipFilePath
528      * @param destDirPath is the output dest path
529      */
unzipFile(String zipFilePath, String destDirPath)530     public static boolean unzipFile(String zipFilePath, String destDirPath) {
531         boolean success = false;
532         File destDir = new File(destDirPath);
533         if (!destDir.exists()) {
534             destDir.mkdirs();
535         }
536         ZipInputStream zipInputStream = null;
537         try {
538             zipInputStream = new ZipInputStream(new FileInputStream(zipFilePath));
539             ZipEntry entry = zipInputStream.getNextEntry();
540             while (entry != null) {
541                 String filePath = destDirPath + File.separator + entry.getName();
542                 if (!matchPattern(filePath)) {
543                     LOG.error("Input invalid file " + filePath + ".");
544                     return false;
545                 }
546                 if (!entry.isDirectory()) {
547                     extractFile(zipInputStream, filePath);
548                 } else {
549                     File dir = new File(filePath);
550                     dir.mkdirs();
551                 }
552                 zipInputStream.closeEntry();
553                 entry = zipInputStream.getNextEntry();
554             }
555             success = true;
556         } catch (IOException e) {
557             LOG.error("FileUtil::unzipFile failed, IOException is " + e.getMessage());
558         } finally {
559             Utility.closeStream(zipInputStream);
560         }
561         return success;
562     }
563 
extractFile(ZipInputStream zipInputStream, String filePath)564     private static void extractFile(ZipInputStream zipInputStream, String filePath) {
565         BufferedOutputStream bufferedOutputStream = null;
566         try {
567             if (!matchPattern(filePath)) {
568                 LOG.error("input invalid file: " + filePath);
569                 throw new BundleException("input invalid file " + filePath + ".");
570             }
571             bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(filePath));
572             byte[] bytes = new byte[BUFFER_SIZE];
573             int readLength = 0;
574             while ((readLength = zipInputStream.read(bytes)) != -1) {
575                 bufferedOutputStream.write(bytes, 0, readLength);
576             }
577         } catch (IOException | BundleException e) {
578             LOG.error("FileUtil::extractFile failed, Exception is " + e.getMessage());
579         } finally {
580             Utility.closeStream(bufferedOutputStream);
581         }
582     }
583 
matchPattern(String path)584     static boolean matchPattern(String path) {
585         if (!Pattern.matches(PATTERN, path)) {
586             LOG.error("input invalid file of " + path + ".");
587             return false;
588         }
589         return true;
590     }
591 
592     /**
593      * getFileSize
594      *
595      * @param filePath is the input file path
596      * @return file length
597      */
getFileSize(String filePath)598     public static long getFileSize(String filePath) {
599         File file = new File(filePath);
600         if (file.exists() && file.isFile()) {
601             return file.length();
602         }
603         String errMsg = "input " + filePath + " is not a valid file.";
604         LOG.error(PackingToolErrMsg.GET_FILE_SIZE_FAILED.toString(errMsg));
605         return 0;
606     }
607 
608     /**
609      * Create a parent directory for a file
610      *
611      * @param file file
612      */
createParentDir(File file)613     public static void createParentDir(File file) {
614         if (file != null && file.getParentFile() != null && !file.getParentFile().exists()) {
615             file.getParentFile().mkdirs();
616         }
617     }
618 
619     /**
620      * copy Stream
621      *
622      * @param inputStream input stream
623      * @param outputStream out stream
624      * @throws IOException IOException.
625      */
copyStream(InputStream inputStream, OutputStream outputStream)626     public static void copyStream(InputStream inputStream, OutputStream outputStream) throws IOException {
627         byte[] buffer = new byte[BUFFER_SIZE];
628         int bytesRead = 0;
629         while ((bytesRead = inputStream.read(buffer)) != -1) {
630             outputStream.write(buffer, 0, bytesRead);
631         }
632     }
633 }
634