1 /* 2 * Copyright (c) 2021-2023 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.BufferedReader; 20 import java.io.ByteArrayOutputStream; 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 29 import java.nio.charset.StandardCharsets; 30 import java.nio.file.attribute.FileTime; 31 32 import java.util.ArrayList; 33 import java.util.Enumeration; 34 import java.util.HashMap; 35 import java.util.List; 36 import java.util.Locale; 37 import java.util.stream.Collectors; 38 import java.util.zip.CRC32; 39 import java.util.zip.CheckedOutputStream; 40 import java.util.zip.ZipEntry; 41 import java.util.zip.ZipFile; 42 import java.util.zip.ZipInputStream; 43 import java.util.zip.ZipOutputStream; 44 45 46 /** 47 * bundle uncompress. 48 * 49 */ 50 public class Uncompress { 51 private static final String HAP_SUFFIX = ".hap"; 52 private static final String APK_SUFFIX = ".apk"; 53 private static final String JSON_SUFFIX = ".json"; 54 private static final String HSP_SUFFIX = ".hsp"; 55 56 private static final String PACK_INFO = "pack.info"; 57 private static final String HARMONY_PROFILE = "config.json"; 58 private static final String MODULE_JSON = "module.json"; 59 private static final String RESOURCE_INDEX = "resources.index"; 60 private static final String RPCID_SC = "rpcid.sc"; 61 private static final String LINUX_FILE_SEPARATOR = "/"; 62 private static final String TEMP_PATH = "temp"; 63 private static final String HAP_SUFFIXI = ".hap"; 64 private static final String ENTRY_TYPE = "entry"; 65 private static final String SYSTEM_ACTION = "action.system.home"; 66 private static final String SYSTEM_WANT_HOME = "ohos.want.action.home"; 67 private static final String SYSTEM_ENTITY = "entity.system.home"; 68 private static final int READ_BUFFER_SIZE = 1024; 69 private static final int BUFFER_SIZE = 10 * 1024; 70 private static final long FILE_TIME = 1546272000000L; 71 private static final String LIBS_DIR_NAME = "libs"; 72 private static final String CUT_ENTRY_FILENAME = "cut_entry.apk"; 73 private static final String SO_SUFFIX = ".so"; 74 private static final String RESOURCE_PATH = "resources/base/profile/"; 75 private static final String TRUE = "true"; 76 private static final String HQF_SUFFIX = ".hqf"; 77 private static final String PATCH_JSON = "patch.json"; 78 private static final String HAP_PREFIX = "HAP"; 79 private static final Log LOG = new Log(Uncompress.class.toString()); 80 81 /** 82 * unpackage entrance. 83 * 84 * @param utility common data 85 * @return unpackageProcess if unpackage succeed 86 */ unpackageProcess(Utility utility)87 static boolean unpackageProcess(Utility utility) { 88 if (utility == null) { 89 LOG.error("Uncompress::unpackageProcess utility is null."); 90 return false; 91 } 92 boolean unpackageResult = true; 93 File destFile = new File(utility.getOutPath()); 94 95 if (!destFile.exists()) { 96 if (!destFile.mkdirs()) { 97 LOG.error("Uncompress::unpackageProcess create out file directory failed!"); 98 return false; 99 } 100 } 101 try { 102 if (!Utility.MODE_HAP.equals(utility.getMode()) || !TRUE.equals(utility.getRpcid())) { 103 if (!utility.getForceRewrite().isEmpty() && "true".equals(utility.getForceRewrite())) { 104 File outPath = new File(utility.getOutPath()); 105 deleteFile(outPath); 106 outPath.mkdirs(); 107 } 108 } 109 switch (utility.getMode()) { 110 case Utility.MODE_HAP: 111 unpackageHapMode(utility); 112 break; 113 case Utility.MODE_HAR: 114 dataTransferAllFiles(utility.getHarPath(), utility.getOutPath()); 115 break; 116 case Utility.MODE_APP: 117 dataTransferFilesByApp(utility, utility.getAppPath(), utility.getOutPath()); 118 break; 119 case Utility.MODE_APPQF: 120 uncompressAPPQFFile(utility); 121 break; 122 case Utility.MODE_HSP: 123 dataTransferAllFiles(utility.getHspPath(), utility.getOutPath()); 124 break; 125 default: 126 LOG.error("Uncompress::unpackageProcess input wrong type!"); 127 throw new BundleException("Uncompress::unpackageProcess input wrong type!"); 128 } 129 } catch (BundleException ignored) { 130 unpackageResult = false; 131 LOG.error("Uncompress::unpackageProcess Bundle exception"); 132 } 133 // return uncompress information. 134 if (!unpackageResult) { 135 LOG.error("Uncompress::unpackageProcess unpackage failed!"); 136 } 137 return unpackageResult; 138 } 139 140 /** 141 * unpack hap. 142 * 143 * @param utility common data 144 */ unpackageHapMode(Utility utility)145 static void unpackageHapMode(Utility utility) throws BundleException { 146 if (!Utility.MODE_HAP.equals(utility.getMode())) { 147 throw new BundleException("Uncompress::unpackageHapMode input wrong unpack mode"); 148 } 149 try { 150 if (TRUE.equals(utility.getRpcid())) { 151 getRpcidFromHap(utility.getHapPath(), utility.getOutPath()); 152 return; 153 } 154 if (TRUE.equals(utility.getUnpackApk())) { 155 unzip(utility, utility.getHapPath(), utility.getOutPath(), APK_SUFFIX); 156 String[] temp = utility.getHapPath().replace("\\", "/").split("/"); 157 String hapName = temp[temp.length - 1]; 158 repackHap(utility.getHapPath(), utility.getOutPath(), hapName, utility.getUnpackApk()); 159 } else { 160 dataTransferAllFiles(utility.getHapPath(), utility.getOutPath()); 161 } 162 } catch (BundleException e) { 163 LOG.error("Uncompress::unpackageHapMode failed"); 164 throw new BundleException("Uncompress::unpackageHapMode failed"); 165 } 166 } 167 168 /** 169 * uncompress app. 170 * 171 * @param utility common data 172 * @return the uncompress result 173 */ uncompressAppByPath(Utility utility)174 static UncompressResult uncompressAppByPath(Utility utility) { 175 UncompressResult compressResult = new UncompressResult(); 176 InputStream input = null; 177 String srcPath = utility.getAppPath(); 178 String parseMode = utility.getParseMode(); 179 180 try { 181 if (UncompressEntrance.PARSE_MODE_HAPLIST.equals(parseMode)) { 182 compressResult = uncompress(utility.getDeviceType(), srcPath, PACK_INFO); 183 } else if (UncompressEntrance.PARSE_MODE_HAPINFO.equals(parseMode)) { 184 compressResult = uncompressHapAndHspFromAppPath(srcPath, utility); 185 } else if (UncompressEntrance.PARSE_MODE_ALL.equals(parseMode)) { 186 compressResult = uncompressAllAppByPath(srcPath); 187 } else { 188 LOG.error("Uncompress::uncompressApp parseMode is invalid!"); 189 compressResult.setResult(false); 190 compressResult.setMessage("ParseApp parseMode is invalid"); 191 } 192 } catch (BundleException e) { 193 LOG.error("Uncompress::uncompressApp Bundle exception"); 194 compressResult.setResult(false); 195 compressResult.setMessage("ParseApp Bundle exception"); 196 } finally { 197 Utility.closeStream(input); 198 } 199 return compressResult; 200 } 201 uncompressHapAndHspFromAppPath( String srcPath, Utility utility)202 private static UncompressResult uncompressHapAndHspFromAppPath( 203 String srcPath, Utility utility) throws BundleException { 204 UncompressResult result = new UncompressResult(); 205 String hapName = utility.getHapName(); 206 if (!hapName.toLowerCase(Locale.ENGLISH).endsWith(HAP_SUFFIX) 207 && !hapName.toLowerCase(Locale.ENGLISH).endsWith(HSP_SUFFIX)) { 208 hapName += HAP_SUFFIX; 209 } 210 ZipFile appFile = null; 211 ZipEntry entry = null; 212 InputStream stream = null; 213 try { 214 appFile = new ZipFile(srcPath); 215 Enumeration<? extends ZipEntry> entries = appFile.entries(); 216 while (entries.hasMoreElements()) { 217 entry = entries.nextElement(); 218 stream = appFile.getInputStream(entry); 219 if (!hapName.equals(entry.getName().toLowerCase(Locale.ENGLISH))) { 220 continue; 221 } 222 UncompressResult hapInfo = uncompressHapByStream("", stream, hapName); 223 if (hapInfo.getProfileInfos() != null && hapInfo.getProfileInfos().size() > 0) { 224 result.addProfileInfo(hapInfo.getProfileInfos().get(0)); 225 result.addProfileInfoStr(hapInfo.getProfileInfosStr().get(0)); 226 } 227 break; 228 } 229 } catch (IOException | BundleException e) { 230 LOG.error("uncompressHapFromAppPath failed!"); 231 throw new BundleException("uncompressHapFromAppPath failed!"); 232 } finally { 233 Utility.closeStream(appFile); 234 Utility.closeStream(stream); 235 } 236 return result; 237 } 238 uncompressAllAppByPath(String srcPath)239 private static UncompressResult uncompressAllAppByPath(String srcPath) throws BundleException { 240 UncompressResult result = new UncompressResult(); 241 ZipFile appFile = null; 242 ZipEntry entry = null; 243 InputStream stream = null; 244 try { 245 appFile = new ZipFile(srcPath); 246 Enumeration<? extends ZipEntry> entries = appFile.entries(); 247 while (entries.hasMoreElements()) { 248 entry = entries.nextElement(); 249 stream = appFile.getInputStream(entry); 250 if (PACK_INFO.equals(entry.getName().toLowerCase(Locale.ENGLISH))) { 251 String packInfo = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8)) 252 .lines().parallel().collect(Collectors.joining(System.lineSeparator())); 253 List<PackInfo> packInfos = JsonUtil.parseHapList("", packInfo); 254 result.setPackInfoStr(packInfo); 255 result.setPackInfos(packInfos); 256 } 257 if (entry.getName().toLowerCase(Locale.ENGLISH).endsWith(HAP_SUFFIX) 258 || entry.getName().toLowerCase(Locale.ENGLISH).endsWith(HSP_SUFFIX)) { 259 UncompressResult hapInfo = uncompressHapByStream("", stream, entry.getName()); 260 if (hapInfo.getProfileInfos() != null && hapInfo.getProfileInfos().size() > 0) { 261 result.addProfileInfo(hapInfo.getProfileInfos().get(0)); 262 result.addProfileInfoStr(hapInfo.getProfileInfosStr().get(0)); 263 } 264 } 265 } 266 result = checkParseAllResult(result); 267 result = obtainLabelAndIcon(result); 268 } catch (IOException | BundleException e) { 269 LOG.error("uncompressAllAppByPath failed!"); 270 throw new BundleException("uncompressAllAppByPath failed!"); 271 } finally { 272 Utility.closeStream(appFile); 273 Utility.closeStream(stream); 274 } 275 return result; 276 } 277 278 279 /** 280 * uncompress app. 281 * 282 * @param utility common data 283 * @param input the InputStream about the app package. 284 * @return the uncompress result 285 */ uncompressAppByInput(Utility utility, InputStream input)286 static UncompressResult uncompressAppByInput(Utility utility, InputStream input) { 287 UncompressResult compressResult = new UncompressResult(); 288 String parseMode = utility.getParseMode(); 289 try { 290 if (!parseMode.isEmpty() && UncompressEntrance.PARSE_MODE_HAPLIST.equals(parseMode)) { 291 compressResult = uncompressByInput(utility.getDeviceType(), input, PACK_INFO, ""); 292 } else if (!parseMode.isEmpty() && UncompressEntrance.PARSE_MODE_HAPINFO.equals(parseMode)) { 293 compressResult = uncompressHapFromAppStream(utility.getDeviceType(), input, utility.getHapName()); 294 } else if (!parseMode.isEmpty() && UncompressEntrance.PARSE_MODE_ALL.equals(parseMode)) { 295 compressResult = uncompressAllFromAppStream(input); 296 } else { 297 LOG.error("Uncompress::uncompressAppByInput parseMode is invalid!"); 298 compressResult.setResult(false); 299 compressResult.setMessage("ParseApp parseMode is invalid"); 300 } 301 } catch (BundleException exception) { 302 LOG.error("Uncompress::uncompressAppByInput Bundle exception"); 303 compressResult.setResult(false); 304 compressResult.setMessage("ParseApp Bundle exception"); 305 } 306 return compressResult; 307 } 308 uncompressHapFromAppStream(String deviceType, InputStream stream, String fileName)309 private static UncompressResult uncompressHapFromAppStream(String deviceType, InputStream stream, String fileName) 310 throws BundleException { 311 String hapFile = fileName; 312 if (!fileName.toLowerCase(Locale.ENGLISH).endsWith(HAP_SUFFIX) 313 && !fileName.toLowerCase(Locale.ENGLISH).endsWith(HSP_SUFFIX)) { 314 hapFile += HAP_SUFFIX; 315 } 316 UncompressResult result = new UncompressResult(); 317 ZipInputStream zipInputStream = null; 318 try { 319 zipInputStream = new ZipInputStream(stream); 320 ZipEntry appEntry; 321 while ((appEntry = zipInputStream.getNextEntry()) != null) { 322 if (appEntry.getName().toLowerCase(Locale.ENGLISH).equals(hapFile)) { 323 result = uncompressHapByStream("", zipInputStream, appEntry.getName()); 324 } 325 } 326 } catch (IOException e) { 327 LOG.error("uncompressHapFromAppStream failed!"); 328 throw new BundleException("uncompressHapFromAppStream failed!"); 329 } finally { 330 Utility.closeStream(zipInputStream); 331 } 332 return result; 333 } 334 uncompressAllFromAppStream(InputStream stream)335 private static UncompressResult uncompressAllFromAppStream(InputStream stream) throws BundleException { 336 UncompressResult result = new UncompressResult(); 337 ZipInputStream zipInputStream = null; 338 ByteArrayOutputStream outputStream = null; 339 try { 340 zipInputStream = new ZipInputStream(stream); 341 ZipEntry entry; 342 while ((entry = zipInputStream.getNextEntry()) != null) { 343 if (PACK_INFO.equals(entry.getName().toLowerCase(Locale.ENGLISH))) { 344 String packInfo = new BufferedReader(new InputStreamReader(zipInputStream, 345 StandardCharsets.UTF_8)).lines().parallel() 346 .collect(Collectors.joining(System.lineSeparator())); 347 List<PackInfo> packInfos = JsonUtil.parseHapList("", packInfo); 348 result.setPackInfoStr(packInfo); 349 result.setPackInfos(packInfos); 350 } 351 if (entry.getName().toLowerCase(Locale.ENGLISH).endsWith(HAP_SUFFIX) 352 || entry.getName().toLowerCase(Locale.ENGLISH).endsWith(HSP_SUFFIX)) { 353 UncompressResult hapResult = uncompressHapByStream("", zipInputStream, entry.getName()); 354 if (hapResult.getProfileInfos() != null && hapResult.getProfileInfos().size() > 0) { 355 result.addProfileInfo(hapResult.getProfileInfos().get(0)); 356 result.addProfileInfoStr(hapResult.getProfileInfosStr().get(0)); 357 } 358 } 359 } 360 result = checkParseAllResult(result); 361 result = obtainLabelAndIcon(result); 362 } catch (IOException | BundleException e) { 363 LOG.error("uncompressAllFromAppStream failed!"); 364 throw new BundleException("uncompressAllFromAppStream failed!"); 365 } finally { 366 Utility.closeStream(zipInputStream); 367 Utility.closeStream(outputStream); 368 } 369 return result; 370 } 371 372 /** 373 * uncompress hap. 374 * 375 * @param utility common data 376 * @return the uncompress result 377 */ uncompressHap(Utility utility)378 static UncompressResult uncompressHap(Utility utility) { 379 UncompressResult compressResult = new UncompressResult(); 380 try { 381 compressResult = uncompressHapByPath(utility.getDeviceType(), utility.getHapPath()); 382 } catch (BundleException ignored) { 383 LOG.error("Uncompress::uncompressHap Bundle exception"); 384 compressResult.setResult(false); 385 compressResult.setMessage("uncompressHap Bundle exception"); 386 } 387 return compressResult; 388 } 389 390 /** 391 * uncompress hap by path, it can adapt stage module and fa module. 392 * 393 * @param deviceType indicates the device type of parse type. 394 * @param hapPath indicates the hap path of hap. 395 * @return the uncompress result 396 */ uncompressHapByPath(String deviceType, String hapPath)397 static UncompressResult uncompressHapByPath(String deviceType, String hapPath) throws BundleException { 398 UncompressResult compressResult = new UncompressResult(); 399 try { 400 if (isModuleHap(hapPath, compressResult)) { 401 compressResult = unCompressModuleHap(deviceType, hapPath, MODULE_JSON); 402 } else { 403 compressResult = uncompress(deviceType, hapPath, HARMONY_PROFILE); 404 compressResult = obtainLabelAndIcon(compressResult); 405 } 406 } catch (BundleException e) { 407 LOG.error("Uncompress::uncompressHapByPath Bundle exception"); 408 throw new BundleException("Uncompress::uncompressHapByPath failed"); 409 } 410 return compressResult; 411 } 412 413 /** 414 * uncompress hap. 415 * 416 * @param utility common data 417 * @param input the InputStream about the app package. 418 * @return the uncompress result 419 */ uncompressHapByInput(Utility utility, InputStream input)420 static UncompressResult uncompressHapByInput(Utility utility, InputStream input) { 421 UncompressResult compressResult = new UncompressResult(); 422 try { 423 compressResult = uncompressHapByStream(utility.getDeviceType(), input, ""); 424 } catch (BundleException ignored) { 425 LOG.error("Uncompress::uncompressHapByInput Bundle exception"); 426 compressResult.setResult(false); 427 compressResult.setMessage("uncompressHapByInput Bundle exception"); 428 } 429 return compressResult; 430 } 431 432 /** 433 * uncompress hap by InputStream, it can adapt stage module and fa module. 434 * 435 * @param deviceType indicates the device type of parse type. 436 * @param stream indicates the input stream of hap. 437 * @return the uncompress result 438 */ uncompressHapByStream(String deviceType, InputStream stream, String hapName)439 static UncompressResult uncompressHapByStream(String deviceType, InputStream stream, 440 String hapName) throws BundleException { 441 UncompressResult compressResult = new UncompressResult(); 442 compressResult = uncompressHapByBigStream(deviceType, stream, hapName); 443 return compressResult; 444 } 445 uncompressHapByBigStream(String deviceType, InputStream stream, String hapName)446 static UncompressResult uncompressHapByBigStream(String deviceType, InputStream stream, String hapName) 447 throws BundleException { 448 UncompressResult compressResult = new UncompressResult(); 449 InputStream fileStream = null; 450 InputStream parseStream = null; 451 File file = null; 452 try { 453 String releativePath = System.getProperty("user.dir"); 454 File directory = new File(releativePath); 455 file = File.createTempFile(HAP_PREFIX, HAP_SUFFIX, directory); 456 writeToTempFile(stream, file); 457 fileStream = new FileInputStream(file); 458 boolean isModule = false; 459 if (isModuleInput(fileStream)) { 460 isModule = true; 461 } 462 parseStream = new FileInputStream(file); 463 if (isModule) { 464 compressResult = uncompressModuleHapByInput(deviceType, parseStream, MODULE_JSON, hapName); 465 } else { 466 compressResult = uncompressByInput(deviceType, parseStream, HARMONY_PROFILE, hapName); 467 compressResult = obtainLabelAndIcon(compressResult); 468 } 469 } catch (IOException e) { 470 LOG.error("uncompressHapByBigStream failed for IO exception!"); 471 throw new BundleException("uncompressHapByBigStream failed for IO exception!"); 472 } finally { 473 Utility.closeStream(fileStream); 474 Utility.closeStream(parseStream); 475 if (file != null) { 476 FileUtils.deleteFile(file.getPath()); 477 } 478 } 479 return compressResult; 480 } 481 482 /** 483 * unzip process 484 * 485 * @param utility common data 486 * @param srcPath source file path 487 * @param destDirPath destination file path 488 * @param suffix suffix for judgment 489 * @throws BundleException FileNotFoundException|IOException. 490 */ unzip(Utility utility, String srcPath, String destDirPath, String suffix)491 private static void unzip(Utility utility, String srcPath, String destDirPath, String suffix) 492 throws BundleException { 493 if (utility == null) { 494 LOG.error("Uncompress::unzip utility is null!"); 495 throw new BundleException("Unzip failed, utility is null"); 496 } 497 498 if (srcPath.isEmpty() || !UncompressVerify.isPathValid(srcPath, true, "")) { 499 LOG.error("Uncompress::unzip srcPath is invalid!"); 500 throw new BundleException("Unzip failed, srcPath is invalid"); 501 } 502 503 if (destDirPath.isEmpty() || !UncompressVerify.isPathValid(destDirPath, false, null)) { 504 LOG.error("Uncompress::unzip destDirPath is invalid!"); 505 throw new BundleException("Unzip failed, destDirPath is invalid"); 506 } 507 unzipFromFile(utility, srcPath, destDirPath, suffix); 508 } 509 510 /** 511 * unzip process from the file 512 * 513 * @param utility common data 514 * @param srcPath source file path 515 * @param destDirPath destination file path 516 * @param suffix suffix for judgment 517 * @throws BundleException FileNotFoundException|IOException. 518 */ unzipFromFile(Utility utility, String srcPath, String destDirPath, String suffix)519 private static void unzipFromFile(Utility utility, String srcPath, String destDirPath, String suffix) 520 throws BundleException { 521 ZipFile zipFile = null; 522 String hapNames = ""; 523 try { 524 zipFile = new ZipFile(new File(srcPath)); 525 if (utility != null && !utility.getDeviceType().isEmpty() 526 && (HAP_SUFFIX.equals(suffix) || HSP_SUFFIX.equals(suffix))) { 527 List<PackInfo> packInfos = uncompress(utility.getDeviceType(), srcPath, PACK_INFO).getPackInfos(); 528 for (PackInfo packinfo : packInfos) { 529 hapNames += packinfo.name + ","; 530 } 531 } 532 533 int entriesNum = 0; 534 for (Enumeration<? extends ZipEntry> entries = zipFile.entries(); entries.hasMoreElements();) { 535 entriesNum++; 536 ZipEntry entry = entries.nextElement(); 537 String entryName = ""; 538 if (entry == null || entry.getName().isEmpty()) { 539 continue; 540 } 541 if (entry.getName().toLowerCase().endsWith(CUT_ENTRY_FILENAME) && 542 "false".equals(utility.getUnpackCutEntryApk())) { 543 continue; 544 } 545 entryName = entry.getName(); 546 if (!entryName.toLowerCase(Locale.ENGLISH).endsWith(suffix) || 547 (!hapNames.isEmpty() && !hapNames.contains(entryName.replace(suffix, "")))) { 548 continue; 549 } 550 String tempDir = destDirPath.replace(File.separator, LINUX_FILE_SEPARATOR); 551 if (HAP_SUFFIX.equals(suffix) && "true".equals(utility.getUnpackApk())) { 552 tempDir = tempDir + LINUX_FILE_SEPARATOR + entryName.replace(suffix, ""); 553 File destFileDir = new File(tempDir); 554 if (!destFileDir.exists()) { 555 destFileDir.mkdir(); 556 } 557 } 558 if (APK_SUFFIX.equals(suffix) && "true".equals(utility.getUnpackApk()) 559 && entryName.contains(LINUX_FILE_SEPARATOR)) { 560 // only unpack shell apk which in the root directory 561 continue; 562 } 563 String tempPath = tempDir + LINUX_FILE_SEPARATOR + entryName; 564 if (!FileUtils.matchPattern(tempPath)) { 565 throw new BundleException("Input invalid file " + tempPath); 566 } 567 File destFile = new File(tempPath); 568 dataTransfer(zipFile, entry, destFile); 569 if (JSON_SUFFIX.equals(suffix)) { 570 break; 571 } else if (HAP_SUFFIX.equals(suffix) && "true".equals(utility.getUnpackApk())) { 572 unzip(utility, tempPath, tempDir, APK_SUFFIX); 573 repackHap(tempPath, tempDir, entryName, utility.getUnpackApk()); 574 } 575 } 576 } catch (IOException | BundleException exception) { 577 LOG.error("Uncompress::unzipInHapMode failed: " + exception.getMessage()); 578 throw new BundleException("Unzip in hap mode failed"); 579 } finally { 580 Utility.closeStream(zipFile); 581 } 582 } 583 584 /** 585 * uncompress dataTransfer 586 * 587 * @param zipFile input zip file 588 * @param entry input file in zip 589 * @param destFile output file path 590 * @throws BundleException FileNotFoundException|IOException. 591 */ dataTransfer(ZipFile zipFile, ZipEntry entry, File destFile)592 private static void dataTransfer(ZipFile zipFile, ZipEntry entry, File destFile) throws BundleException { 593 InputStream fileInputStream = null; 594 FileOutputStream fileOutStream = null; 595 try { 596 if (!FileUtils.matchPattern(destFile.getCanonicalPath())) { 597 LOG.error("Input invalid file " + destFile); 598 throw new BundleException("Input invalid file" + destFile.getCanonicalPath()); 599 } 600 fileInputStream = zipFile.getInputStream(entry); 601 fileOutStream = new FileOutputStream(destFile); 602 byte[] data = new byte[BUFFER_SIZE]; 603 int count = fileInputStream.read(data); 604 int total = 0; 605 while (count > 0) { 606 fileOutStream.write(data, 0, count); 607 total += count; 608 count = fileInputStream.read(data); 609 } 610 } catch (IOException | BundleException exception) { 611 LOG.error("Uncompress::dataTransfer file " + exception.getMessage()); 612 throw new BundleException("DataTransfer failed"); 613 } finally { 614 Utility.closeStream(fileOutStream); 615 Utility.closeStream(fileInputStream); 616 } 617 } 618 619 /** 620 * uncompress dataTransfer all files. 621 * 622 * @param srcPath source file path 623 * @param destDirPath destination file path 624 * @throws BundleException FileNotFoundException|IOException. 625 */ dataTransferAllFiles(String srcPath, String destDirPath)626 private static void dataTransferAllFiles(String srcPath, String destDirPath) throws BundleException { 627 ZipFile zipFile = null; 628 try { 629 if (!FileUtils.matchPattern(srcPath)) { 630 throw new BundleException("Input invalid file " + srcPath); 631 } 632 zipFile = new ZipFile(new File(srcPath)); 633 int entriesNum = 0; 634 for (Enumeration<? extends ZipEntry> entries = zipFile.entries(); entries.hasMoreElements();) { 635 entriesNum++; 636 ZipEntry entry = entries.nextElement(); 637 if (entry == null) { 638 continue; 639 } 640 String tempPath = destDirPath + LINUX_FILE_SEPARATOR + entry.getName(); 641 File destFile = new File(tempPath); 642 if (destFile != null && destFile.getParentFile() != null && !destFile.getParentFile().exists()) { 643 destFile.getParentFile().mkdirs(); 644 } 645 dataTransfer(zipFile, entry, destFile); 646 } 647 } catch (FileNotFoundException ignored) { 648 LOG.error("Uncompress::unzipApk file not found exception"); 649 throw new BundleException("Unzip Apk failed"); 650 } catch (IOException exception) { 651 LOG.error("Uncompress::unzipApk io exception: " + exception.getMessage()); 652 throw new BundleException("Unzip Apk failed"); 653 } finally { 654 Utility.closeStream(zipFile); 655 } 656 } 657 dataTransferFilesByApp(Utility utility, String srcPath, String destDirPath)658 private static void dataTransferFilesByApp(Utility utility, String srcPath, String destDirPath) 659 throws BundleException { 660 ZipFile zipFile = null; 661 try { 662 zipFile = new ZipFile(new File(srcPath)); 663 int entriesNum = 0; 664 for (Enumeration<? extends ZipEntry> entries = zipFile.entries(); entries.hasMoreElements();) { 665 entriesNum++; 666 ZipEntry entry = entries.nextElement(); 667 if (entry == null) { 668 continue; 669 } 670 String filePath = destDirPath + LINUX_FILE_SEPARATOR + entry.getName(); 671 if (!FileUtils.matchPattern(filePath)) { 672 throw new BundleException("Input invalid path " + filePath); 673 } 674 File destFile = new File(filePath); 675 if (destFile != null && destFile.getParentFile() != null && !destFile.getParentFile().exists()) { 676 destFile.getParentFile().mkdirs(); 677 } 678 boolean isUnpackApk = "true".equals(utility.getUnpackApk()); 679 if (isUnpackApk && filePath.toLowerCase().endsWith(HAP_SUFFIX)) { 680 dataTransfer(zipFile, entry, destFile); 681 unzip(utility, filePath, destDirPath, APK_SUFFIX); 682 String[] temp = filePath.replace("\\", "/").split("/"); 683 String hapName = ""; 684 if (temp.length > 0) { 685 hapName = temp[temp.length - 1]; 686 } 687 repackHap(filePath, destDirPath, hapName, utility.getUnpackApk()); 688 } else { 689 dataTransfer(zipFile, entry, destFile); 690 } 691 } 692 } catch (IOException | BundleException exception) { 693 LOG.error("Uncompress::unzipApk file failed " + exception.getMessage()); 694 throw new BundleException("Unzip Apk failed"); 695 } finally { 696 Utility.closeStream(zipFile); 697 } 698 } 699 getResourceDataFromHap(ZipFile zipFile)700 private static byte[] getResourceDataFromHap(ZipFile zipFile) throws BundleException, IOException { 701 int entriesNum = 0; 702 InputStream indexInputStream = null; 703 try { 704 for (Enumeration<? extends ZipEntry> entries = zipFile.entries(); entries.hasMoreElements();) { 705 entriesNum++; 706 ZipEntry indexEntry = entries.nextElement(); 707 if (indexEntry == null) { 708 continue; 709 } 710 if (indexEntry != null && !"".equals(indexEntry.getName()) && 711 indexEntry.getName().toLowerCase().endsWith(RESOURCE_INDEX)) { 712 indexInputStream = zipFile.getInputStream(indexEntry); 713 return getByte(indexInputStream); 714 } 715 } 716 } finally { 717 Utility.closeStream(indexInputStream); 718 } 719 return null; 720 } 721 unZipHapFileFromHapFile(String srcPath)722 private static HapZipInfo unZipHapFileFromHapFile(String srcPath) 723 throws BundleException, IOException { 724 HapZipInfo hapZipInfo = new HapZipInfo(); 725 ZipFile zipFile = null; 726 if (!FileUtils.matchPattern(srcPath)) { 727 LOG.error("Input invalid path " + srcPath); 728 throw new BundleException("Input invalid path " + srcPath); 729 } 730 try { 731 File srcFile = new File(srcPath); 732 zipFile = new ZipFile(srcFile); 733 hapZipInfo.setHarmonyProfileJsonStr(FileUtils.getFileStringFromZip(HARMONY_PROFILE, zipFile)); 734 hapZipInfo.setResDataBytes(getResourceDataFromHap(zipFile)); 735 hapZipInfo.setPackInfoJsonStr(FileUtils.getFileStringFromZip(PACK_INFO, zipFile)); 736 hapZipInfo.setHapFileName(getHapNameWithoutSuffix(srcFile.getName())); 737 } finally { 738 Utility.closeStream(zipFile); 739 } 740 return hapZipInfo; 741 } 742 743 /** 744 * uncompress from specified file name 745 * 746 * @param deviceType device type 747 * @param srcPath source file path 748 * @param fileName uncompress file name 749 * @return the uncompress result 750 * @throws BundleException FileNotFoundException|IOException. 751 */ uncompress(String deviceType, String srcPath, String fileName)752 private static UncompressResult uncompress(String deviceType, String srcPath, String fileName) 753 throws BundleException { 754 if (srcPath.isEmpty() || fileName.isEmpty()) { 755 LOG.error("Uncompress::uncompress srcPath, fileName is empty!"); 756 throw new BundleException("Uncompress failed, srcPath or fileName is empty"); 757 } 758 759 UncompressResult result = new UncompressResult(); 760 try { 761 HapZipInfo hapZipInfo = unZipHapFileFromHapFile(srcPath); 762 if (isPackInfo(fileName)) { 763 uncompressPackInfo(deviceType, hapZipInfo, result); 764 } else { 765 uncompressProfileInfo(hapZipInfo, result); 766 } 767 } catch (IOException exception) { 768 LOG.error("Uncompress::uncompress io exception: " + exception.getMessage()); 769 throw new BundleException("Uncompress failed"); 770 } 771 return result; 772 } 773 uncompressPackInfo(String deviceType, HapZipInfo hapZipInfo, UncompressResult uncomperssResult)774 private static void uncompressPackInfo(String deviceType, HapZipInfo hapZipInfo, UncompressResult uncomperssResult) 775 throws BundleException { 776 List<PackInfo> packInfos = JsonUtil.parseHapList(deviceType, hapZipInfo.getPackInfoJsonStr()); 777 uncomperssResult.setPackInfoStr(hapZipInfo.getPackInfoJsonStr()); 778 uncomperssResult.setPackInfos(packInfos); 779 } 780 uncompressProfileInfo(HapZipInfo hapZipInfo, UncompressResult uncomperssResult)781 private static void uncompressProfileInfo(HapZipInfo hapZipInfo, UncompressResult uncomperssResult) 782 throws BundleException { 783 ProfileInfo profileInfo = JsonUtil.parseProfileInfo(hapZipInfo.getHarmonyProfileJsonStr(), 784 hapZipInfo.getResDataBytes(), hapZipInfo.getPackInfoJsonStr(), hapZipInfo.getHapFileName()); 785 profileInfo.hapName = hapZipInfo.getHapFileName(); 786 profileInfo.appInfo.setBundleType(getFABundleType(profileInfo)); 787 uncomperssResult.addProfileInfoStr(hapZipInfo.getHarmonyProfileJsonStr()); 788 uncomperssResult.addProfileInfo(profileInfo); 789 } 790 getFABundleType(ProfileInfo profileInfo)791 private static String getFABundleType(ProfileInfo profileInfo) { 792 String bundleType = "app"; 793 if (profileInfo.hapInfo.distro.installationFree == 1) { 794 bundleType = "atomicService"; 795 } 796 return bundleType; 797 } 798 unZipHapFileFromInputStream(InputStream input)799 private static HapZipInfo unZipHapFileFromInputStream(InputStream input) throws BundleException, IOException { 800 BufferedInputStream bufIn = null; 801 ZipInputStream zipIn = null; 802 BufferedReader bufferedReader = null; 803 HapZipInfo hapZipInfo = new HapZipInfo(); 804 try { 805 ZipEntry entry = null; 806 bufIn = new BufferedInputStream(input); 807 zipIn = new ZipInputStream(bufIn); 808 int entriesNum = 0; 809 while ((entry = zipIn.getNextEntry()) != null) { 810 entriesNum++; 811 if (entry.getName().toLowerCase().endsWith(RESOURCE_INDEX)) { 812 hapZipInfo.setResDataBytes(getByte(zipIn)); 813 continue; 814 } 815 if (isPackInfo(entry.getName())) { 816 bufferedReader = new BufferedReader(new InputStreamReader(zipIn)); 817 hapZipInfo.setPackInfoJsonStr(readStringFromInputStream(zipIn, bufferedReader)); 818 continue; 819 } 820 if (isHarmonyProfile(entry.getName())) { 821 bufferedReader = new BufferedReader(new InputStreamReader(zipIn)); 822 hapZipInfo.setHarmonyProfileJsonStr(readStringFromInputStream(zipIn, bufferedReader)); 823 } 824 } 825 } finally { 826 Utility.closeStream(bufferedReader); 827 Utility.closeStream(bufIn); 828 Utility.closeStream(zipIn); 829 } 830 return hapZipInfo; 831 } 832 readStringFromInputStream(ZipInputStream zipIn, BufferedReader bufferedReader)833 private static String readStringFromInputStream(ZipInputStream zipIn, BufferedReader bufferedReader) 834 throws IOException { 835 String line; 836 StringBuilder sb = new StringBuilder(); 837 while ((line = bufferedReader.readLine()) != null) { 838 sb.append(line); 839 } 840 return sb.toString(); 841 } 842 843 /** 844 * uncompress process by InputStream 845 * 846 * @param deviceType device type 847 * @param input the InputStream about the package. 848 * @param fileName uncompress file name 849 * @return the uncompress result 850 * @throws BundleException FileNotFoundException|IOException. 851 */ uncompressByInput(String deviceType, InputStream input, String fileName, String hapName)852 private static UncompressResult uncompressByInput(String deviceType, InputStream input, 853 String fileName, String hapName) throws BundleException { 854 UncompressResult result = new UncompressResult(); 855 try { 856 HapZipInfo hapZipInfo = unZipHapFileFromInputStream(input); 857 hapZipInfo.setHapFileName(hapName); 858 if (isPackInfo(fileName)) { 859 uncompressPackInfo(deviceType, hapZipInfo, result); 860 } else { 861 uncompressProfileInfo(hapZipInfo, result); 862 } 863 } catch (IOException exception) { 864 LOG.error("Uncompress::uncompressByInput io exception: " + exception.getMessage()); 865 throw new BundleException("Uncompress by input failed"); 866 } 867 return result; 868 } 869 870 /** 871 * uncompress process by InputStream 872 * 873 * @param deviceType device type 874 * @param input the InputStream about the package. 875 * @param fileName uncompress file name 876 * @return the module uncompress result 877 * @throws BundleException FileNotFoundException|IOException. 878 */ uncompressModuleByInput(String deviceType, InputStream input, String fileName, String hapName)879 private static ModuleResult uncompressModuleByInput(String deviceType, InputStream input, 880 String fileName, String hapName) throws BundleException { 881 ModuleResult result = new ModuleResult(); 882 try { 883 HapZipInfo hapZipInfo = unZipModuleHapFileFromInputStream(input); 884 hapZipInfo.setHapFileName(hapName); 885 if (isPackInfo(fileName)) { 886 // for parse app 887 } else { 888 uncompressModuleJsonInfo(hapZipInfo, result); 889 } 890 } catch (BundleException exception) { 891 LOG.error("Uncompress::uncompressByInput io exception: " + exception.getMessage()); 892 throw new BundleException("Uncompress by input failed"); 893 } 894 return result; 895 } 896 897 /** 898 * Get entry byte array. 899 * 900 * @param zis the InputStream about the entry. 901 * @return Return the entry byte array. 902 * @throws BundleException FileNotFoundException|IOException. 903 */ getByte(InputStream zis)904 private static byte[] getByte(InputStream zis) throws BundleException { 905 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 906 byte[] buf = null; 907 try { 908 byte[] temp = new byte[READ_BUFFER_SIZE]; 909 int length = 0; 910 911 while ((length = zis.read(temp, 0, READ_BUFFER_SIZE)) != -1) { 912 bos.write(temp, 0, length); 913 } 914 915 buf = bos.toByteArray(); 916 } catch (IOException e) { 917 LOG.error("Uncompress::getByte io exception: " + e.getMessage()); 918 throw new BundleException("Get byte failed"); 919 } finally { 920 Utility.closeStream(bos); 921 } 922 return buf; 923 } 924 925 /** 926 * repack hap 927 * 928 * @param srcPath source file path 929 * @param destDirPath destination file path 930 * @param fileName target file name 931 * @param unpackApk unpackApk flag 932 * @throws BundleException FileNotFoundException|IOException. 933 */ repackHap(String srcPath, String destDirPath, String fileName, String unpackApk)934 private static void repackHap(String srcPath, String destDirPath, String fileName, String unpackApk) 935 throws BundleException { 936 if (srcPath.isEmpty() || destDirPath.isEmpty() || fileName.isEmpty()) { 937 LOG.error("Uncompress::repackHap srcPath, destDirPath or fileName is empty!"); 938 throw new BundleException("Repack hap failed, srcPath, destDirPath or fileName is empty"); 939 } 940 941 if (!UncompressVerify.isPathValid(srcPath, true, "")) { 942 LOG.error("Uncompress::repackHap srcPath is invalid!"); 943 throw new BundleException("Repack hap failed, srcPath is invalid"); 944 } 945 946 if (!UncompressVerify.isPathValid(destDirPath, false, null)) { 947 LOG.error("Uncompress::repackHap destDirPath is invalid!"); 948 throw new BundleException("Repack hap failed, destDirPath is invalid"); 949 } 950 951 String tempDir = destDirPath.replace(File.separator, LINUX_FILE_SEPARATOR) + LINUX_FILE_SEPARATOR + 952 TEMP_PATH; 953 dataTransferAllFiles(srcPath, tempDir); 954 packFilesByPath(tempDir, destDirPath, fileName, unpackApk); 955 File deleteFile = new File(tempDir); 956 deleteFile(deleteFile); 957 } 958 959 /** 960 * compress file directory. 961 * 962 * @param srcPath source file path 963 * @param destDirPath destination file path 964 * @param fileName target file name 965 * @param unpackApk unpackApk flag 966 * @throws BundleException FileNotFoundException|IOException. 967 */ packFilesByPath(String srcPath, String destDirPath, String fileName, String unpackApk)968 private static void packFilesByPath(String srcPath, String destDirPath, String fileName, String unpackApk) 969 throws BundleException { 970 if (srcPath.isEmpty() || destDirPath.isEmpty() || fileName.isEmpty()) { 971 LOG.error("Uncompress::packFilesByPath srcPath, destDirPath or fileName is empty!"); 972 throw new BundleException("Pack files by path failed, srcPath, destDirPath or fileName is empty"); 973 } 974 975 if (!UncompressVerify.isPathValid(srcPath, false, null) || 976 !UncompressVerify.isPathValid(destDirPath, false, null)) { 977 LOG.error("Uncompress::packFilesByPath srcPath or destDirPath is invalid!"); 978 throw new BundleException("Pack files by path failed, srcPath or destDirPath is invalid"); 979 } 980 981 File srcDir = new File(srcPath); 982 File[] srcFiles = srcDir.listFiles(); 983 if (srcFiles == null) { 984 return; 985 } 986 FileOutputStream fileOut = null; 987 CheckedOutputStream checkedOut = null; 988 ZipOutputStream zipOut = null; 989 990 try { 991 String zipPath = destDirPath + LINUX_FILE_SEPARATOR + fileName; 992 if (!FileUtils.matchPattern(zipPath)) { 993 throw new BundleException("Input invalid file" + zipPath); 994 } 995 File zipFile = new File(zipPath); 996 fileOut = new FileOutputStream(zipFile); 997 checkedOut = new CheckedOutputStream(fileOut, new CRC32()); 998 zipOut = new ZipOutputStream(checkedOut); 999 for (int i = 0; i < srcFiles.length; i++) { 1000 File srcFile = srcFiles[i]; 1001 if (srcFile.isDirectory()) { 1002 if (srcFile.getPath().toLowerCase(Locale.ENGLISH).endsWith(LIBS_DIR_NAME)) { 1003 compressDirectory(srcFile, "", zipOut, true); 1004 } else { 1005 compressDirectory(srcFile, "", zipOut, false); 1006 } 1007 } else { 1008 if (srcFile.getPath().toLowerCase(Locale.ENGLISH).endsWith(APK_SUFFIX) && 1009 "true".equals(unpackApk)) { 1010 continue; 1011 } 1012 compressFile(srcFile, "", zipOut, false); 1013 } 1014 } 1015 } catch (FileNotFoundException | BundleException exception) { 1016 LOG.error("Uncompress::packFilesByPath " + exception.getMessage()); 1017 throw new BundleException("Pack files by path failed"); 1018 } finally { 1019 Utility.closeStream(zipOut); 1020 Utility.closeStream(checkedOut); 1021 Utility.closeStream(fileOut); 1022 } 1023 } 1024 1025 /** 1026 * compress file directory. 1027 * 1028 * @param dir file directory 1029 * @param baseDir base path for file 1030 * @param zipOut zip outPutStream 1031 * @param isCompression if need compression 1032 * @throws BundleException FileNotFoundException|IOException. 1033 */ compressDirectory(File dir, String baseDir, ZipOutputStream zipOut, boolean isCompression)1034 private static void compressDirectory(File dir, String baseDir, ZipOutputStream zipOut, boolean isCompression) 1035 throws BundleException { 1036 File[] files = dir.listFiles(); 1037 if (files == null) { 1038 return; 1039 } 1040 for (File file : files) { 1041 if (file.isDirectory()) { 1042 compressDirectory(file, baseDir + dir.getName() + File.separator, zipOut, isCompression); 1043 } else { 1044 compressFile(file, baseDir + dir.getName() + File.separator, zipOut, isCompression); 1045 } 1046 } 1047 } 1048 1049 /** 1050 * compress process. 1051 * 1052 * @param srcFile source file to zip 1053 * @param baseDir base path for file 1054 * @param zipOut zip outPutStream 1055 * @param isCompression if need compression 1056 * @throws BundleException FileNotFoundException|IOException. 1057 */ compressFile(File srcFile, String baseDir, ZipOutputStream zipOut, boolean isCompression)1058 private static void compressFile(File srcFile, String baseDir, ZipOutputStream zipOut, boolean isCompression) 1059 throws BundleException { 1060 FileInputStream fileInputStream = null; 1061 BufferedInputStream bufferedInputStream = null; 1062 1063 try { 1064 String entryName = (baseDir + srcFile.getName()).replace(File.separator, LINUX_FILE_SEPARATOR); 1065 ZipEntry zipEntry = new ZipEntry(entryName); 1066 boolean isNeedCompress = isCompression; 1067 if (srcFile.isFile() && srcFile.getName().toLowerCase(Locale.ENGLISH).endsWith(SO_SUFFIX)) { 1068 isNeedCompress = false; 1069 } 1070 if (isNeedCompress) { 1071 zipEntry.setMethod(ZipEntry.DEFLATED); 1072 } else { 1073 zipEntry.setMethod(ZipEntry.STORED); 1074 zipEntry.setCompressedSize(srcFile.length()); 1075 zipEntry.setSize(srcFile.length()); 1076 CRC32 crc = getCrcFromFile(srcFile); 1077 zipEntry.setCrc(crc.getValue()); 1078 } 1079 FileTime fileTime = FileTime.fromMillis(FILE_TIME); 1080 zipEntry.setLastAccessTime(fileTime); 1081 zipEntry.setLastModifiedTime(fileTime); 1082 zipOut.putNextEntry(zipEntry); 1083 byte[] data = new byte[BUFFER_SIZE]; 1084 fileInputStream = new FileInputStream(srcFile); 1085 bufferedInputStream = new BufferedInputStream(fileInputStream); 1086 int count = bufferedInputStream.read(data); 1087 while (count > 0) { 1088 zipOut.write(data, 0, count); 1089 count = bufferedInputStream.read(data); 1090 } 1091 } catch (FileNotFoundException ignored) { 1092 LOG.error("Uncompress::compressFile file not found exception"); 1093 throw new BundleException("Compress file failed"); 1094 } catch (IOException exception) { 1095 LOG.error("Uncompress::compressFile io exception: " + exception.getMessage()); 1096 throw new BundleException("Compress file failed"); 1097 } finally { 1098 Utility.closeStream(fileInputStream); 1099 Utility.closeStream(bufferedInputStream); 1100 } 1101 } 1102 1103 /** 1104 * get CRC32 from file. 1105 * 1106 * @param file source file 1107 * @return CRC32 1108 * @throws BundleException FileNotFoundException|IOException. 1109 */ getCrcFromFile(File file)1110 private static CRC32 getCrcFromFile(File file) throws BundleException { 1111 FileInputStream fileInputStream = null; 1112 CRC32 crc = new CRC32(); 1113 try { 1114 fileInputStream = new FileInputStream(file); 1115 byte[] buffer = new byte[BUFFER_SIZE]; 1116 1117 int count = fileInputStream.read(buffer); 1118 while (count > 0) { 1119 crc.update(buffer, 0, count); 1120 count = fileInputStream.read(buffer); 1121 } 1122 } catch (FileNotFoundException ignored) { 1123 LOG.error("Uncompressor::getCrcFromFile file not found exception"); 1124 throw new BundleException("Get Crc from file failed"); 1125 } catch (IOException exception) { 1126 LOG.error("Uncompressor::getCrcFromFile io exception: " + exception.getMessage()); 1127 throw new BundleException("Get Crc from file failed"); 1128 } finally { 1129 Utility.closeStream(fileInputStream); 1130 } 1131 return crc; 1132 } 1133 1134 /** 1135 * delete file 1136 * 1137 * @param file the file to be deleted 1138 */ deleteFile(File file)1139 private static void deleteFile(File file) { 1140 if (file.exists()) { 1141 if (file.isDirectory()) { 1142 File[] files = file.listFiles(); 1143 for (int i = 0; i < files.length; i++) { 1144 deleteFile(files[i]); 1145 } 1146 } 1147 file.delete(); 1148 } 1149 } 1150 1151 /** 1152 * check 1153 * 1154 * @param result the result of parse app all mode 1155 * @return return the result of checkParseAllResult. 1156 */ checkParseAllResult(UncompressResult result)1157 private static UncompressResult checkParseAllResult(UncompressResult result) { 1158 UncompressResult errorResult = new UncompressResult(); 1159 errorResult.setResult(false); 1160 errorResult.setMessage("App package is invalid."); 1161 if (result == null || result.getPackInfos() == null || result.getProfileInfos() == null) { 1162 return errorResult; 1163 } 1164 1165 List<PackInfo> packInfos = result.getPackInfos(); 1166 List<ProfileInfo> profileInfos = result.getProfileInfos(); 1167 int packInfoSize = packInfos.size(); 1168 int profileInfoSize = profileInfos.size(); 1169 if (packInfoSize == 0 || profileInfoSize == 0 || packInfoSize != profileInfoSize) { 1170 LOG.error("Uncompress::checkParseAllResult error, hapNum is invalid in app"); 1171 return errorResult; 1172 } 1173 1174 for (int i = 0; i < packInfoSize; i++) { 1175 if (packInfos.get(i) == null || packInfos.get(i).name.isEmpty()) { 1176 return errorResult; 1177 } 1178 boolean isHave = false; 1179 for (int j = 0; j < profileInfoSize; j++) { 1180 if (profileInfos.get(j) == null || profileInfos.get(j).hapName.isEmpty()) { 1181 return errorResult; 1182 } 1183 if (comparePackAndProfile(packInfos.get(i), profileInfos.get(j))) { 1184 isHave = true; 1185 break; 1186 } 1187 } 1188 if (!isHave) { 1189 return errorResult; 1190 } 1191 } 1192 1193 return result; 1194 } 1195 1196 /** 1197 * get label and icon for application 1198 * 1199 * @param result the result of parse app all mode 1200 * @return return the result which contains icon and label 1201 */ obtainLabelAndIcon(UncompressResult result)1202 private static UncompressResult obtainLabelAndIcon(UncompressResult result) { 1203 List<ProfileInfo> profileInfos = result.getProfileInfos(); 1204 if (profileInfos.isEmpty()) { 1205 return result; 1206 } 1207 for (ProfileInfo profileInfo : profileInfos) { 1208 if (profileInfo == null) { 1209 continue; 1210 } 1211 HapInfo hapInfo = profileInfo.hapInfo; 1212 if (hapInfo == null) { 1213 continue; 1214 } 1215 Distro distro = hapInfo.distro; 1216 if (distro == null) { 1217 continue; 1218 } 1219 String moduleType = distro.moduleType; 1220 if (ENTRY_TYPE.equals(moduleType.toLowerCase(Locale.ENGLISH))) { 1221 return obtainInnerLabelAndIcon(result, hapInfo, distro); 1222 } 1223 } 1224 return result; 1225 } 1226 1227 /** 1228 * get label and icon for application 1229 * 1230 * @param result the result of parse app all mode 1231 * @param hapInfo hap info of entry hap 1232 * @return return the result which contains icon and label 1233 */ obtainInnerLabelAndIcon(UncompressResult result, HapInfo hapInfo, Distro distro)1234 private static UncompressResult obtainInnerLabelAndIcon(UncompressResult result, HapInfo hapInfo, Distro distro) { 1235 List<AbilityInfo> abilities = hapInfo.abilities; 1236 if ((abilities == null) || (abilities.isEmpty())) { 1237 result.setLabel(distro.moduleName); 1238 return result; 1239 } 1240 int size = 0; 1241 for (AbilityInfo info : abilities) { 1242 if (info == null) { 1243 size++; 1244 continue; 1245 } 1246 if ((info.skills == null) || (info.skills.isEmpty())) { 1247 continue; 1248 } 1249 for (SkillInfo skill : info.skills) { 1250 if (skill == null) { 1251 continue; 1252 } 1253 List<String> actions = skill.actions; 1254 List<String> entities = skill.entities; 1255 if ((!actions.isEmpty()) && (actions.contains(SYSTEM_ACTION) || actions.contains(SYSTEM_WANT_HOME)) 1256 && (!entities.isEmpty()) && (entities.contains(SYSTEM_ENTITY))) { 1257 result.setLabel(info.label); 1258 result.setIcon(info.icon); 1259 return result; 1260 } 1261 } 1262 } 1263 if (size == abilities.size()) { 1264 result.setLabel(distro.moduleName); 1265 return result; 1266 } 1267 for (AbilityInfo info : abilities) { 1268 if (info != null) { 1269 result.setLabel(info.label); 1270 result.setIcon(info.icon); 1271 break; 1272 } 1273 } 1274 return result; 1275 } 1276 1277 isHarmonyProfile(String fileName)1278 private static boolean isHarmonyProfile(String fileName) { 1279 return HARMONY_PROFILE.equals(fileName); 1280 } 1281 isPackInfo(String fileName)1282 private static boolean isPackInfo(String fileName) { 1283 return PACK_INFO.equals(fileName); 1284 } 1285 getHapNameWithoutSuffix(String hapFileName)1286 private static String getHapNameWithoutSuffix(String hapFileName) { 1287 if (hapFileName == null || hapFileName.isEmpty() || hapFileName.lastIndexOf(".") == -1) { 1288 return ""; 1289 } 1290 return hapFileName.substring(0, hapFileName.lastIndexOf(".")); 1291 } 1292 unZipModuleHapFile(String srcPath)1293 private static HapZipInfo unZipModuleHapFile(String srcPath) 1294 throws BundleException, IOException { 1295 HapZipInfo hapZipInfo = new HapZipInfo(); 1296 ZipFile zipFile = null; 1297 try { 1298 File srcFile = new File(srcPath); 1299 zipFile = new ZipFile(srcFile); 1300 getProfileJson(zipFile, hapZipInfo.resourcemMap); 1301 hapZipInfo.setHarmonyProfileJsonStr(FileUtils.getFileStringFromZip(MODULE_JSON, zipFile)); 1302 hapZipInfo.setPackInfoJsonStr(FileUtils.getFileStringFromZip(PACK_INFO, zipFile)); 1303 hapZipInfo.setResDataBytes(getResourceDataFromHap(zipFile)); 1304 hapZipInfo.setHapFileName(getHapNameWithoutSuffix(srcFile.getName())); 1305 } finally { 1306 Utility.closeStream(zipFile); 1307 } 1308 return hapZipInfo; 1309 } 1310 1311 /** 1312 * uncompress from HapZipInfo 1313 * 1314 * @param hapZipInfo hap zip info 1315 * @return the parse moduleResult 1316 * @throws BundleException FileNotFoundException|IOException. 1317 */ uncompressModuleJsonInfo(HapZipInfo hapZipInfo, ModuleResult moduleResult)1318 private static void uncompressModuleJsonInfo(HapZipInfo hapZipInfo, ModuleResult moduleResult) 1319 throws BundleException { 1320 ModuleProfileInfo moduleProfileInfo = JsonUtil.parseModuleProfileInfo(hapZipInfo.getHarmonyProfileJsonStr(), 1321 hapZipInfo.getResDataBytes(), hapZipInfo.getPackInfoJsonStr(), hapZipInfo.getHapFileName(), 1322 hapZipInfo.resourcemMap); 1323 moduleProfileInfo.hapName = hapZipInfo.getHapFileName(); 1324 moduleResult.addModuleProfileInfo(moduleProfileInfo); 1325 moduleResult.moduleProfileStr.add(hapZipInfo.getHarmonyProfileJsonStr()); 1326 } 1327 1328 /** 1329 * uncompress from specified file name 1330 * 1331 * @param deviceType device type 1332 * @param srcPath source file path 1333 * @param fileName uncompress file name 1334 * @return the uncompress result 1335 * @throws BundleException FileNotFoundException|IOException. 1336 */ uncompressModule(String deviceType, String srcPath, String fileName)1337 private static ModuleResult uncompressModule(String deviceType, String srcPath, String fileName) 1338 throws BundleException { 1339 if (srcPath.isEmpty() || fileName.isEmpty()) { 1340 LOG.error("Uncompress::uncompressModule srcPath, fileName is empty!"); 1341 throw new BundleException("uncompressModule failed, srcPath or fileName is empty"); 1342 } 1343 ModuleResult moduleResult = new ModuleResult(); 1344 try { 1345 HapZipInfo hapZipInfo = unZipModuleHapFile(srcPath); 1346 uncompressModuleJsonInfo(hapZipInfo, moduleResult); 1347 if (moduleResult.packInfos.isEmpty() && !hapZipInfo.getPackInfoJsonStr().isEmpty()) { 1348 moduleResult.packInfos = JsonUtil.parsePackInfos(hapZipInfo.getPackInfoJsonStr()); 1349 } 1350 } catch (IOException exception) { 1351 moduleResult.setResult(false); 1352 LOG.error("Uncompress::uncompressModule parseMode is invalid!"); 1353 } 1354 return moduleResult; 1355 } 1356 1357 /** 1358 * uncompress module hap. 1359 * 1360 * @param deviceType indicates the device type of uncompress mode. 1361 * @param srcPath indicates the path type of hap. 1362 * @param fileName indicates json file name. 1363 * @return the uncompress result 1364 */ unCompressModuleHap(String deviceType, String srcPath, String fileName)1365 static UncompressResult unCompressModuleHap(String deviceType, String srcPath, String fileName) 1366 throws BundleException{ 1367 if (srcPath.isEmpty() || fileName.isEmpty()) { 1368 LOG.error("Uncompress::uncompress srcPath, fileName is empty!"); 1369 throw new BundleException("Uncompress failed, srcPath or fileName is empty"); 1370 } 1371 UncompressResult uncomperssResult = new UncompressResult(); 1372 ModuleResult moduleResult = new ModuleResult(); 1373 try { 1374 moduleResult = uncompressModule(deviceType, srcPath, fileName); 1375 ModuleAdaption moduleAdaption = new ModuleAdaption(); 1376 uncomperssResult = moduleAdaption.convertToUncompressResult(moduleResult); 1377 } catch (BundleException ignored) { 1378 LOG.error("Uncompress::uncompressHap Bundle exception"); 1379 uncomperssResult.setResult(false); 1380 uncomperssResult.setMessage("uncompressHap Bundle exception"); 1381 } 1382 return uncomperssResult; 1383 } 1384 /** 1385 * get all resource in profile. 1386 * 1387 * @param zipFile is the hap file 1388 * @return the parse resource result 1389 */ getProfileJson(ZipFile zipFile, HashMap<String, String> resourceMap)1390 static void getProfileJson(ZipFile zipFile, HashMap<String, String> resourceMap) throws BundleException { 1391 try { 1392 final Enumeration<? extends ZipEntry> entries = zipFile.entries(); 1393 while (entries.hasMoreElements()) { 1394 final ZipEntry entry = entries.nextElement(); 1395 if (entry.getName().contains(RESOURCE_PATH)) { 1396 String filePath = entry.getName(); 1397 String fileName = filePath.replaceAll(RESOURCE_PATH, ""); 1398 String fileContent = FileUtils.getFileStringFromZip(filePath, zipFile); 1399 resourceMap.put(fileName, fileContent); 1400 } 1401 } 1402 } catch (IOException e) { 1403 LOG.error("Uncompress::getProfileJson IOException"); 1404 throw new BundleException("Uncompress::getProfileJson failed"); 1405 } 1406 } 1407 1408 /** 1409 * uncompress module hap. 1410 * 1411 * @param deviceType indicates the deviceType of parse hap. 1412 * @param input the InputStream about the app package. 1413 * @param fileName the file name of json file. 1414 * @return the uncompress result 1415 */ uncompressModuleHapByInput(String deviceType, InputStream input, String fileName, String hapName)1416 static UncompressResult uncompressModuleHapByInput(String deviceType, 1417 InputStream input, String fileName, String hapName) { 1418 UncompressResult uncompressResult = new UncompressResult(); 1419 ModuleResult moduleResult = new ModuleResult(); 1420 try { 1421 moduleResult = uncompressModuleByInput(deviceType, input, MODULE_JSON, hapName); 1422 ModuleAdaption moduleAdaption = new ModuleAdaption(); 1423 uncompressResult = moduleAdaption.convertToUncompressResult(moduleResult); 1424 } catch (BundleException ignored) { 1425 LOG.error("Uncompress::uncompressHapByInput Bundle exception"); 1426 uncompressResult.setResult(false); 1427 uncompressResult.setMessage("uncompressHapByInput Bundle exception"); 1428 } 1429 return uncompressResult; 1430 } 1431 1432 /** 1433 * unzip module hap from zip file. 1434 * 1435 * @param input Indicates the InputStream about the package. 1436 * @return Return the uncomperss result of parseHap 1437 */ unZipModuleHapFileFromInputStream(InputStream input)1438 private static HapZipInfo unZipModuleHapFileFromInputStream(InputStream input) throws BundleException { 1439 BufferedInputStream bufIn = null; 1440 ZipInputStream zipIn = null; 1441 BufferedReader bufferedReader = null; 1442 HapZipInfo hapZipInfo = new HapZipInfo(); 1443 try { 1444 ZipEntry entry = null; 1445 bufIn = new BufferedInputStream(input); 1446 zipIn = new ZipInputStream(bufIn); 1447 while ((entry = zipIn.getNextEntry()) != null) { 1448 if (entry.getName().toLowerCase().endsWith(RESOURCE_INDEX)) { 1449 hapZipInfo.setResDataBytes(getByte(zipIn)); 1450 continue; 1451 } 1452 if (isPackInfo(entry.getName())) { 1453 bufferedReader = new BufferedReader(new InputStreamReader(zipIn)); 1454 hapZipInfo.setPackInfoJsonStr(readStringFromInputStream(zipIn, bufferedReader)); 1455 continue; 1456 } 1457 if (MODULE_JSON.equals(entry.getName())) { 1458 bufferedReader = new BufferedReader(new InputStreamReader(zipIn)); 1459 hapZipInfo.setHarmonyProfileJsonStr(readStringFromInputStream(zipIn, bufferedReader)); 1460 } 1461 if (entry.getName().contains(RESOURCE_PATH)) { 1462 bufferedReader = new BufferedReader(new InputStreamReader(zipIn)); 1463 String filePath = entry.getName(); 1464 String fileName = filePath.replaceAll(RESOURCE_PATH, ""); 1465 String fileContent = readStringFromInputStream(zipIn, bufferedReader); 1466 hapZipInfo.pushResourceMap(fileName, fileContent); 1467 } 1468 } 1469 } catch (BundleException | IOException e) { 1470 LOG.error("unZipModuleHapFileFromInputStream failed!"); 1471 throw new BundleException("unZipModuleHapFileFromInputStream failed!"); 1472 } finally { 1473 Utility.closeStream(bufferedReader); 1474 Utility.closeStream(bufIn); 1475 Utility.closeStream(zipIn); 1476 } 1477 return hapZipInfo; 1478 } 1479 1480 /** 1481 * Parse the hap type. 1482 * 1483 * @param hapPath Indicates the hap path. 1484 * @param compressResult Indicates the result of parse hap. 1485 * @return Return the type result of isModuleHap 1486 */ isModuleHap(String hapPath, UncompressResult compressResult)1487 public static boolean isModuleHap(String hapPath, UncompressResult compressResult) { 1488 ZipFile zipFile = null; 1489 try { 1490 zipFile = new ZipFile(new File(hapPath)); 1491 final Enumeration<? extends ZipEntry> entries = zipFile.entries(); 1492 while (entries.hasMoreElements()) { 1493 final ZipEntry entry = entries.nextElement(); 1494 if (MODULE_JSON.equals(entry.getName())) { 1495 return true; 1496 } 1497 } 1498 } catch (FileNotFoundException ignored) { 1499 LOG.error("Uncompress::isModuleHap file not found exception"); 1500 compressResult.setResult(false); 1501 compressResult.setMessage("judge is module failed"); 1502 } catch (IOException exception) { 1503 LOG.error("Uncompress::isModuleHap io exception: " + exception.getMessage()); 1504 compressResult.setResult(false); 1505 compressResult.setMessage("judge is module failed"); 1506 } finally { 1507 Utility.closeStream(zipFile); 1508 } 1509 return false; 1510 } 1511 1512 /** 1513 * Parse the hap type. 1514 * 1515 * @param input Indicates the hap FileInputStream. 1516 * @return Return the type result of isModuleHap. 1517 */ isModuleInput(InputStream input)1518 public static boolean isModuleInput(InputStream input) throws BundleException { 1519 BufferedInputStream bufIn = null; 1520 ZipInputStream zipIn = null; 1521 BufferedReader bufferedReader = null; 1522 try { 1523 ZipEntry entry = null; 1524 bufIn = new BufferedInputStream(input); 1525 zipIn = new ZipInputStream(bufIn); 1526 while((entry = zipIn.getNextEntry()) != null) { 1527 if (entry.getName().toLowerCase().endsWith(MODULE_JSON)) { 1528 return true; 1529 } 1530 } 1531 } catch (IOException ignored) { 1532 LOG.error("Uncompress::isModuleHap judge failed!"); 1533 throw new BundleException("Uncompress::isModuleHap judge failed!"); 1534 } finally { 1535 Utility.closeStream(bufferedReader); 1536 Utility.closeStream(bufIn); 1537 Utility.closeStream(zipIn); 1538 } 1539 return false; 1540 } 1541 1542 /** 1543 * create file output stream from InputStream . 1544 * 1545 * @param stream Indicates the input stream of hap. 1546 * @param file Indicates the temp file to save input stream. 1547 */ writeToTempFile(InputStream stream, File file)1548 static void writeToTempFile(InputStream stream, File file) throws BundleException { 1549 FileOutputStream fileOutputStream = null; 1550 try { 1551 if (file == null) { 1552 LOG.error("file not exist!"); 1553 } 1554 fileOutputStream = new FileOutputStream(file); 1555 int bytesRead = 0; 1556 byte[] buffer = new byte[1024]; 1557 while ((bytesRead = stream.read(buffer)) != -1) { 1558 fileOutputStream.write(buffer, 0, bytesRead); 1559 } 1560 } catch (IOException e) { 1561 LOG.error("writeToTempFile failed!"); 1562 throw new BundleException("writeToTempFile failed!"); 1563 } finally { 1564 Utility.closeStream(fileOutputStream); 1565 } 1566 } 1567 1568 /** 1569 * copy rpcid.sc file. 1570 * 1571 * @param srcFile Indicates the path of hap. 1572 * @param rpcidPath Indicates the output path of rpcid.sc file. 1573 */ getRpcidFromHap(String srcFile, String rpcidPath)1574 static void getRpcidFromHap(String srcFile, String rpcidPath) throws BundleException { 1575 ZipFile zipFile = null; 1576 InputStream inputStream = null; 1577 FileOutputStream outputStream = null; 1578 try { 1579 zipFile = new ZipFile(srcFile); 1580 String filePath = null; 1581 final Enumeration<? extends ZipEntry> entries = zipFile.entries(); 1582 while (entries.hasMoreElements()) { 1583 final ZipEntry entry = entries.nextElement(); 1584 if (RPCID_SC.equals(entry.getName())) { 1585 filePath = entry.getName(); 1586 break; 1587 } 1588 } 1589 if (filePath != null) { 1590 File rpcidFile = new File(rpcidPath, RPCID_SC); 1591 if (rpcidFile.getParentFile() != null && !rpcidFile.getParentFile().exists()) { 1592 rpcidFile.getParentFile().mkdirs(); 1593 } 1594 ZipEntry rpcidEntry = zipFile.getEntry(filePath); 1595 inputStream = zipFile.getInputStream(rpcidEntry); 1596 byte[] buffer = new byte[1024]; 1597 int noBytes = 0; 1598 outputStream = new FileOutputStream(rpcidFile); 1599 while((noBytes = inputStream.read(buffer)) != -1) { 1600 outputStream.write(buffer, 0, noBytes); 1601 } 1602 } else { 1603 LOG.error("Uncompress::getRpcidFromHap hap has no rpcid.sc file"); 1604 throw new BundleException("Uncompress::getRpcidFromHap hap has no rpcid.sc file"); 1605 } 1606 } catch (IOException e) { 1607 LOG.error("Uncompress::getRpcidFromHap IOException " + e.getMessage()); 1608 throw new BundleException("Uncompress::getRpcidFromHap failed"); 1609 } finally { 1610 Utility.closeStream(zipFile); 1611 Utility.closeStream(inputStream); 1612 Utility.closeStream(outputStream); 1613 } 1614 } 1615 1616 /** 1617 * parse resource.index file. 1618 * 1619 * @param srcPath Indicates the path of hap. 1620 */ getResourceFromHap(String srcPath)1621 static List<ResourceIndexResult> getResourceFromHap(String srcPath) throws BundleException, IOException { 1622 ZipFile zipFile = null; 1623 try { 1624 File srcFile = new File(srcPath); 1625 zipFile = new ZipFile(srcFile); 1626 byte[] data = getResourceDataFromHap(zipFile); 1627 return ResourcesParser.getAllDataItem(data); 1628 } finally { 1629 Utility.closeStream(zipFile); 1630 } 1631 } 1632 1633 /** 1634 * uncompress appqf file. 1635 * 1636 * @param utility is the common args for input. 1637 * @throws BundleException if uncompress failed. 1638 */ uncompressAPPQFFile(Utility utility)1639 private static void uncompressAPPQFFile(Utility utility) throws BundleException { 1640 ZipFile zipFile = null; 1641 try { 1642 zipFile = new ZipFile(new File(utility.getAPPQFPath())); 1643 int entriesNum = 0; 1644 for (Enumeration<? extends ZipEntry> entries = zipFile.entries(); entries.hasMoreElements();) { 1645 entriesNum++; 1646 ZipEntry entry = entries.nextElement(); 1647 if (entry == null) { 1648 continue; 1649 } 1650 String filePath = utility.getOutPath() + File.separator + entry.getName(); 1651 if (!FileUtils.matchPattern(filePath)) { 1652 LOG.error("uncompressAPPQFFile: Input invalid file" + filePath); 1653 throw new BundleException("uncompressAPPQFFile: Input invalid file" + filePath); 1654 } 1655 File destFile = new File(filePath); 1656 if (destFile != null && destFile.getParentFile() != null && !destFile.getParentFile().exists()) { 1657 destFile.getParentFile().mkdirs(); 1658 } 1659 dataTransfer(zipFile, entry, destFile); 1660 } 1661 } catch (FileNotFoundException ignored) { 1662 LOG.error("Uncompress::uncompressAPPQFFile file not found exception"); 1663 throw new BundleException("Uncompress::uncompressAPPQFFile file not found"); 1664 } catch (IOException exception) { 1665 LOG.error("Uncompress::uncompressAPPQFFile io exception"); 1666 throw new BundleException("Uncompress::uncompressAPPQFFile io exception"); 1667 } finally { 1668 Utility.closeStream(zipFile); 1669 } 1670 } 1671 1672 /** 1673 * parse appqf file, . 1674 * 1675 * @param appqfPath is the path of appqf file. 1676 * @throws BundleException if uncompress failed. 1677 * @throws IOException if IOException happened. 1678 */ parseAPPQFFile(String appqfPath)1679 public static List<HQFInfo> parseAPPQFFile(String appqfPath) throws BundleException { 1680 List<String> patchList = new ArrayList<>(); 1681 ZipFile zipFile = null; 1682 InputStream stream = null; 1683 ZipInputStream zipInputStream = null; 1684 try { 1685 zipFile = new ZipFile(appqfPath); 1686 Enumeration<? extends ZipEntry> entries = zipFile.entries(); 1687 while (entries.hasMoreElements()) { 1688 ZipEntry appqfEntry = entries.nextElement(); 1689 stream = zipFile.getInputStream(appqfEntry); 1690 if (!appqfEntry.getName().endsWith(HQF_SUFFIX)) { 1691 continue; 1692 } 1693 zipInputStream = new ZipInputStream(stream); 1694 String patchJson = readPatchJson(zipInputStream); 1695 if (patchJson == null) { 1696 continue; 1697 } 1698 patchList.add(patchJson); 1699 } 1700 } catch (IOException e) { 1701 LOG.error("parseAPPQFFile failed!"); 1702 throw new BundleException("parseAPPQFFile failed!"); 1703 } finally { 1704 Utility.closeStream(zipFile); 1705 Utility.closeStream(stream); 1706 Utility.closeStream(zipInputStream); 1707 } 1708 return parsePatchJson(patchList); 1709 } 1710 readPatchJson(ZipInputStream zipInputStream)1711 private static String readPatchJson(ZipInputStream zipInputStream) throws BundleException { 1712 String patchJson = null; 1713 ZipEntry hqfEntry; 1714 try { 1715 while ((hqfEntry = zipInputStream.getNextEntry()) != null) { 1716 if (!PATCH_JSON.equals(hqfEntry.getName())) { 1717 continue; 1718 } 1719 patchJson = new BufferedReader(new InputStreamReader(zipInputStream, 1720 StandardCharsets.UTF_8)).lines().parallel() 1721 .collect(Collectors.joining(System.lineSeparator())); 1722 } 1723 } catch (IOException e) { 1724 LOG.error("readPatchJson failed!"); 1725 throw new BundleException("readPatchJson failed!"); 1726 } 1727 return patchJson; 1728 } 1729 parsePatchJson(List<String> patchList)1730 private static List<HQFInfo> parsePatchJson(List<String> patchList) throws BundleException { 1731 List<HQFInfo> hqfInfoList = new ArrayList<>(); 1732 for (String patchJson : patchList) { 1733 hqfInfoList.add(JsonUtil.parsePatch(patchJson)); 1734 } 1735 return hqfInfoList; 1736 } 1737 comparePackAndProfile(PackInfo packInfo, ProfileInfo profileInfo)1738 private static boolean comparePackAndProfile(PackInfo packInfo, ProfileInfo profileInfo) { 1739 if (profileInfo.hapName.replace(HAP_SUFFIXI, "").equals(packInfo.name.replace(HAP_SUFFIXI, ""))) { 1740 return true; 1741 } 1742 if (profileInfo.hapName.replace(HSP_SUFFIX, "").equals(packInfo.name.replace(HSP_SUFFIX, ""))) { 1743 return true; 1744 } 1745 return false; 1746 } 1747 } 1748