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