1 /* 2 * Copyright (c) 2021-2022 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 com.ohos.hapsigntool.utils; 17 18 import com.google.gson.Gson; 19 import com.google.gson.GsonBuilder; 20 import com.ohos.hapsigntool.error.ERROR; 21 import org.apache.logging.log4j.LogManager; 22 import org.apache.logging.log4j.Logger; 23 24 import java.io.BufferedWriter; 25 import java.io.ByteArrayOutputStream; 26 import java.io.Closeable; 27 import java.io.DataOutputStream; 28 import java.io.File; 29 import java.io.FileInputStream; 30 import java.io.FileNotFoundException; 31 import java.io.FileOutputStream; 32 import java.io.IOException; 33 import java.io.InputStream; 34 import java.io.OutputStream; 35 import java.io.OutputStreamWriter; 36 import java.nio.charset.Charset; 37 38 /** 39 * Common file operation. 40 * 41 * @since 2021/12/28 42 */ 43 public final class FileUtils { 44 45 /** 46 * LOGGER. 47 */ 48 private static final Logger LOGGER = LogManager.getLogger(FileUtils.class); 49 /** 50 * add GSON static. 51 */ 52 public static final Gson GSON = (new GsonBuilder()).disableHtmlEscaping().create(); 53 /** 54 * add GSON_PRETTY_PRINT static. 55 */ 56 public static final Gson GSON_PRETTY_PRINT = (new GsonBuilder()).disableHtmlEscaping().setPrettyPrinting().create(); 57 /** 58 * File reader block size 59 */ 60 public static final int FILE_BUFFER_BLOCK = 4096; 61 /** 62 * File end 63 */ 64 public static final int FILE_END = -1; 65 /** 66 * Expected split string length 67 */ 68 public static final int SPLIT_LENGTH = 2; 69 70 private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; 71 FileUtils()72 private FileUtils() { 73 } 74 75 /** 76 * Close closeable quietly. 77 * 78 * @param closeable closeable 79 */ close(Closeable closeable)80 public static void close(Closeable closeable) { 81 if (closeable != null) { 82 try { 83 closeable.close(); 84 } catch (IOException exception) { 85 LOGGER.debug(exception.getMessage(), exception); 86 } 87 } 88 } 89 90 /** 91 * Read byte from input file. 92 * 93 * @param file Which file to read 94 * @return byte content 95 * @throws IOException Read failed 96 */ readFile(File file)97 public static byte[] readFile(File file) throws IOException { 98 return read(new FileInputStream(file)); 99 } 100 101 /** 102 * Read byte from input stream. 103 * 104 * @param input Input stream 105 * @return File content 106 * @throws IOException Read failed 107 */ read(InputStream input)108 public static byte[] read(InputStream input) throws IOException { 109 try (ByteArrayOutputStream output = new ByteArrayOutputStream()) { 110 byte[] buffer = new byte[FILE_BUFFER_BLOCK]; 111 int read; 112 while ((read = input.read(buffer)) != FILE_END) { 113 output.write(buffer, 0, read); 114 } 115 return output.toByteArray(); 116 } finally { 117 close(input); 118 } 119 } 120 121 /** 122 * Out put content to file. 123 * 124 * @param content Which content to out put 125 * @param output File to write 126 * @throws IOException Write failed 127 */ write(byte[] content, File output)128 public static void write(byte[] content, File output) throws IOException { 129 try (FileOutputStream out = new FileOutputStream(output)) { 130 for (byte con : content) { 131 out.write(con); 132 } 133 } 134 } 135 136 /** 137 * Check file exist or not. 138 * 139 * @param filePath File path 140 * @return Is file exist 141 */ isFileExist(String filePath)142 public static boolean isFileExist(String filePath) { 143 return new File(filePath).exists(); 144 } 145 146 /** 147 * Throw runtime exception if not allowed file type. 148 * 149 * @param filePath file path 150 * @param types Such as "txt" "json" "mp3" 151 */ validFileType(String filePath, String... types)152 public static void validFileType(String filePath, String... types) { 153 String suffix = getSuffix(filePath); 154 ValidateUtils.throwIfNotMatches(!StringUtils.isEmpty(suffix), 155 ERROR.NOT_SUPPORT_ERROR, "Not support file: " + filePath); 156 boolean isMatches = false; 157 for (String type : types) { 158 if (StringUtils.isEmpty(type)) { 159 continue; 160 } 161 if (type.equalsIgnoreCase(suffix)) { 162 isMatches = true; 163 break; 164 } 165 } 166 ValidateUtils.throwIfNotMatches(isMatches, ERROR.NOT_SUPPORT_ERROR, "Not support file: " + filePath); 167 } 168 169 /** 170 * Get suffix of file. 171 * 172 * @param filePath file path 173 * @return file suffix. Such as "txt" "json" "p12" 174 */ getSuffix(String filePath)175 public static String getSuffix(String filePath) { 176 if (StringUtils.isEmpty(filePath)) { 177 return ""; 178 } 179 File file = new File(filePath); 180 String fileName = file.getName(); 181 String[] temps = fileName.split("\\."); 182 if (temps.length < SPLIT_LENGTH) { 183 return ""; 184 } 185 return temps[temps.length - 1]; 186 } 187 188 /** 189 * Write data in file to output stream 190 * 191 * @param file input file path. 192 * @param dos output stream. 193 * @return true, if write successfully. 194 */ writeFileToDos(String file, DataOutputStream dos)195 public static boolean writeFileToDos(String file, DataOutputStream dos) { 196 if (dos == null) { 197 return false; 198 } 199 File src = new File(file); 200 try (FileInputStream fileStream = new FileInputStream(src)) { 201 int temp; 202 byte[] buf = new byte[FILE_BUFFER_BLOCK]; 203 while ((temp = fileStream.read(buf)) > 0) { 204 dos.write(buf, 0, temp); 205 } 206 return true; 207 } catch (FileNotFoundException e) { 208 LOGGER.error("Failed to get input stream object."); 209 } catch (IOException e) { 210 LOGGER.error("Failed to read or write data."); 211 } 212 return false; 213 } 214 215 /** 216 * Write byte array to output stream 217 * 218 * @param data byte array 219 * @param dos output stream 220 * @return true, if write successfully. 221 */ writeByteToDos(byte[] data, DataOutputStream dos)222 public static boolean writeByteToDos(byte[] data, DataOutputStream dos) { 223 try { 224 dos.write(data); 225 } catch (IOException e) { 226 LOGGER.error("Faile to write data to output stream."); 227 return false; 228 } 229 return true; 230 } 231 232 /** 233 * Get length of file. 234 * 235 * @param filePath input file path. 236 * @return long value of file length. 237 */ getFileLen(String filePath)238 public static long getFileLen(String filePath) { 239 File file = new File(filePath); 240 if (file.exists() && file.isFile()) { 241 return file.length(); 242 } 243 return -1; 244 } 245 246 /** 247 * Write byte array data to output file. 248 * 249 * @param signHeadByte byte array data. 250 * @param outFile output file path. 251 * @return true, if write successfully. 252 */ writeByteToOutFile(byte[] signHeadByte, String outFile)253 public static boolean writeByteToOutFile(byte[] signHeadByte, String outFile) { 254 try (OutputStream ops = new FileOutputStream(outFile, true)) { 255 ops.write(signHeadByte, 0, signHeadByte.length); 256 ops.flush(); 257 return true; 258 } catch (FileNotFoundException e) { 259 LOGGER.error("Failed to get output stream object, outfile: " + outFile); 260 } catch (IOException e) { 261 LOGGER.error("Failed to write data to ops, outfile: " + outFile); 262 } 263 return false; 264 } 265 266 /** 267 * Check input file is valid. 268 * 269 * @param file input file. 270 * @throws IOException file is a directory or can't be read. 271 */ isValidFile(File file)272 public static void isValidFile(File file) throws IOException { 273 if (!file.exists()) { 274 throw new FileNotFoundException("File '" + file + "' does not exist"); 275 } 276 277 if (file.isDirectory()) { 278 throw new IOException("File '" + file + "' exists but is a directory"); 279 } 280 281 if (!file.canRead()) { 282 throw new IOException("File '" + file + "' cannot be read"); 283 } 284 } 285 286 /** 287 * Open an input stream of input file safely. 288 * @param file input file. 289 * @return an input stream of input file 290 * @throws IOException file is a directory or can't be read. 291 */ openInputStream(File file)292 public static FileInputStream openInputStream(File file) throws IOException { 293 isValidFile(file); 294 return new FileInputStream(file); 295 } 296 toByteArray(final InputStream input, final int size)297 private static byte[] toByteArray(final InputStream input, final int size) throws IOException { 298 if (size < 0) { 299 throw new IllegalArgumentException("Size must be equal or greater than zero: " + size); 300 } 301 302 if (size == 0) { 303 return EMPTY_BYTE_ARRAY; 304 } 305 306 final byte[] data = new byte[size]; 307 int offset = 0; 308 int read; 309 310 while (offset < size && (read = input.read(data, offset, size - offset)) != FILE_END) { 311 offset += read; 312 } 313 314 if (offset != size) { 315 throw new IOException("Unexpected read size. current: " + offset + ", expected: " + size); 316 } 317 318 return data; 319 } 320 321 /** 322 * Read file to byte array. 323 * 324 * @param file input file. 325 * @return byte array of file-content. 326 * @throws IOException fill exception 327 */ readFileToByteArray(File file)328 public static byte[] readFileToByteArray(File file) throws IOException { 329 try (InputStream in = openInputStream(file)) { 330 final long fileLength = file.length(); 331 if (fileLength > Integer.MAX_VALUE) { 332 throw new IllegalArgumentException("Size cannot be greater than Integer max value: " + fileLength); 333 } 334 return toByteArray(in, (int) fileLength); 335 } 336 } 337 338 /** 339 * Write a string to file 340 * 341 * @param source String will be written. 342 * @param filePath path to write file. 343 * @param charset a charset 344 * @throws IOException write error. 345 */ writeStringToFile(String source, String filePath, Charset charset)346 public static void writeStringToFile(String source, String filePath, Charset charset) throws IOException { 347 try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( 348 new FileOutputStream(filePath), charset))) { 349 writer.write(source); 350 writer.flush(); 351 } 352 } 353 } 354