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.BufferedOutputStream; 19 import java.io.BufferedInputStream; 20 import java.io.BufferedReader; 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 import java.io.OutputStream; 29 import java.nio.charset.StandardCharsets; 30 import java.nio.file.attribute.FileTime; 31 import java.util.Locale; 32 import java.util.regex.Matcher; 33 import java.util.regex.Pattern; 34 import java.util.zip.CRC32; 35 import java.util.zip.CheckedOutputStream; 36 import java.util.zip.ZipInputStream; 37 import java.util.zip.ZipEntry; 38 import java.util.zip.ZipFile; 39 import java.util.zip.ZipOutputStream; 40 import java.util.Enumeration; 41 import java.util.ArrayList; 42 import java.util.List; 43 import java.util.Arrays; 44 45 46 /** 47 * bundle compressor class, compress file and directory. 48 * 49 */ 50 public class Compressor { 51 private static final String JSON_SUFFIX = ".json"; 52 private static final String INFO_SUFFIX = ".info"; 53 private static final String HAP_SUFFIX = ".hap"; 54 private static final String PNG_SUFFIX = ".png"; 55 private static final String UPPERCASE_PNG_SUFFIX = ".PNG"; 56 private static final String CONFIG_JSON = "config.json"; 57 private static final String MODULE_JSON = "module.json"; 58 private static final String CODE = "code"; 59 private static final String NAME = "name"; 60 private static final String VERSION = "\"version\""; 61 private static final String VERSION_CODE = "\"versionCode\""; 62 private static final String NULL_DIR_NAME = ""; 63 private static final String RES_DIR_NAME = "res/"; 64 private static final String RESOURCES_DIR_NAME = "resources/"; 65 private static final String LIBS_DIR_NAME = "libs/"; 66 private static final String ASSETS_DIR_NAME = "assets/"; 67 private static final String SO_DIR_NAME = "maple/"; 68 private static final String SO_ARM64_DIR_NAME = "maple/arm64/"; 69 private static final String LINUX_FILE_SEPARATOR = "/"; 70 private static final String DISTRO = "distro"; 71 private static final String FORMS = "forms"; 72 private static final String MODULE_NAME = "module-name"; 73 private static final String MODULE_NAME_NEW = "moduleName"; 74 private static final String JSON_END = "}"; 75 private static final String SEMICOLON = "\""; 76 private static final String APPLICATION = "deviceConfig"; 77 private static final String COMPRESS_NATIVE_LIBS = "compressNativeLibs"; 78 private static final String SHARED_LIBS_DIR_NAME = "shared_libs/"; 79 private static final String DEVICE_TYPE = "deviceType"; 80 private static final String DEVICE_TYPE_FITNESSWATCH = "fitnessWatch"; 81 private static final String DEVICE_TYPE_FITNESSWATCH_NEW = "liteWearable"; 82 private static final String COLON = ":"; 83 private static final String COMMA = ","; 84 private static final String ENTRYCARD_NAME = "EntryCard/"; 85 private static final String PACKINFO_NAME = "pack.info"; 86 private static final String ENTRYCARD_BASE_NAME = "base"; 87 private static final String ENTRYCARD_SNAPSHOT_NAME = "snapshot"; 88 private static final String VERTICAL = "vertical"; 89 private static final String HORIZONTAL = "horizontal"; 90 private static final String CAR = "car"; 91 private static final String TV = "tv"; 92 private static final String SDIP = "sdip"; 93 private static final String MDIP = "mdip"; 94 private static final String WEARABLE = "wearable"; 95 private static final String PIC_1X2 = "1x2"; 96 private static final String PIC_2X2 = "2x2"; 97 private static final String PIC_2X4 = "2x4"; 98 private static final String PIC_4X4 = "4x4"; 99 private static final String REGEX_LANGUAGE = "^[a-z]{2}$"; 100 private static final String REGEX_SCRIPT = "^[A-Z][a-z]{3}$"; 101 private static final String REGEX_COUNTRY = "^[A-Z]{2,3}|[0-9]{3}$"; 102 private static final String REGEX_ORIENTATION = "^vertical|horizontal$"; 103 private static final String REGEX_DEVICE_TYPE = "^phone|tablet|car|tv|wearable|liteWearable$"; 104 private static final String REGEX_SCREEN_DENSITY = "^sdpi|mdpi|ldpi|xldpi|xxldpi$"; 105 private static final String REGEX_COLOR_MODE = "^light|dark$"; 106 private static final String REGEX_SHAPE = "^circle$"; 107 private static final String JS_PATH = "js/"; 108 private static final String ETS_PATH = "ets/"; 109 110 111 // set timestamp to get fixed MD5 112 private static final long FILE_TIME = 1546272000000L; 113 114 // set buffer size of each read 115 private static final int BUFFER_SIZE = 10 * 1024; 116 private static final Log LOG = new Log(Compressor.class.toString()); 117 private static String versionCode = ""; 118 private static String versionName = ""; 119 120 private ZipOutputStream zipOut = null; 121 private boolean mIsContain2x2EntryCard = true; 122 123 private List<String> list = new ArrayList<String>(); 124 private List<String> formNamesList = new ArrayList<String>(); 125 private List<String> fileNameList = new ArrayList<String>(); 126 private List<String> supportDimensionsList = Arrays.asList(PIC_1X2, PIC_2X2, PIC_2X4, PIC_4X4); 127 128 /** 129 * check path if is a module.json file 130 * 131 * @param path path input 132 * @return true if path is a module file 133 */ isModuleJSON(String path)134 private static boolean isModuleJSON(String path) 135 { 136 File file = new File(path); 137 if ((file.isFile()) && file.getName().equals(MODULE_JSON)) { 138 return true; 139 } 140 return false; 141 } 142 143 /** 144 * start compress. 145 * file orders as follows: 146 * for hap: 1.config.json 2.lib 3.res 4.assets 5.*.so 6.*.dex 7.*.apk 8.resources.index 147 * for app: 1.certificate 2.signature 3.pack.info 4.hap (1 and 2 may not be used) 148 * 149 * @param utility common data 150 * @return compressProcess if compress succeed 151 */ compressProcess(Utility utility)152 public boolean compressProcess(Utility utility) { 153 boolean compressResult = true; 154 File destFile = new File(utility.getOutPath()); 155 156 // if out file directory not exist, mkdirs. 157 File outParentFile = destFile.getParentFile(); 158 if ((outParentFile != null) && (!outParentFile.exists())) { 159 if (!outParentFile.mkdirs()) { 160 LOG.error("Compressor::compressProcess create out file parent directory failed!"); 161 return false; 162 } 163 } 164 165 FileOutputStream fileOut = null; 166 CheckedOutputStream checkedOut = null; 167 try { 168 fileOut = new FileOutputStream(destFile); 169 checkedOut = new CheckedOutputStream(fileOut, new CRC32()); 170 zipOut = new ZipOutputStream(checkedOut); 171 if (Utility.MODE_HAP.equals(utility.getMode())) { 172 if (isModuleJSON(utility.getJsonPath())) { 173 compressHapModeForModule(utility); 174 } else { 175 compressHapMode(utility); 176 } 177 } else if (Utility.MODE_HAR.equals(utility.getMode())) { 178 compressHarMode(utility); 179 } else if (Utility.MODE_APP.equals(utility.getMode())) { 180 compressAppMode(utility); 181 } else { 182 compressPackResMode(utility); 183 } 184 } catch (FileNotFoundException exception) { 185 compressResult = false; 186 LOG.error("Compressor::compressProcess file not found exception" + exception.getMessage()); 187 } catch (BundleException ignored) { 188 compressResult = false; 189 LOG.error("Compressor::compressProcess Bundle exception"); 190 } finally { 191 closeZipOutputStream(); 192 Utility.closeStream(zipOut); 193 Utility.closeStream(checkedOut); 194 Utility.closeStream(fileOut); 195 } 196 197 // if compress failed, delete out file. 198 if (!compressResult) { 199 LOG.error("Compressor::compressProcess compress failed!"); 200 if (!destFile.delete()) { 201 LOG.error("Compressor::compressProcess delete dest file failed"); 202 } 203 } 204 return compressResult; 205 } 206 207 /** 208 * compress in hap mode. 209 * 210 * @param utility common data 211 * @throws BundleException FileNotFoundException|IOException. 212 */ compressHapMode(Utility utility)213 private void compressHapMode(Utility utility) throws BundleException { 214 pathToFile(utility, utility.getJsonPath(), NULL_DIR_NAME, false); 215 216 pathToFile(utility, utility.getProfilePath(), NULL_DIR_NAME, false); 217 218 if (!utility.getIndexPath().isEmpty() && !utility.getModuleName().isEmpty()) { 219 String assetsPath = ASSETS_DIR_NAME + utility.getModuleName() + LINUX_FILE_SEPARATOR; 220 pathToFile(utility, utility.getIndexPath(), assetsPath, false); 221 } 222 223 if (!utility.getLibPath().isEmpty()) { 224 pathToFile(utility, utility.getLibPath(), LIBS_DIR_NAME, utility.isCompressNativeLibs()); 225 } 226 227 if (!utility.getFilePath().isEmpty()) { 228 pathToFile(utility, utility.getFilePath(), NULL_DIR_NAME, false); 229 } 230 231 if (!utility.getResPath().isEmpty() && !utility.getModuleName().isEmpty()) { 232 String resPath = ASSETS_DIR_NAME + utility.getModuleName() + LINUX_FILE_SEPARATOR 233 + RESOURCES_DIR_NAME; 234 if (DEVICE_TYPE_FITNESSWATCH.equals(utility.getDeviceType().replace("\"", "").trim()) || 235 DEVICE_TYPE_FITNESSWATCH_NEW.equals(utility.getDeviceType().replace("\"", "").trim())) { 236 resPath = RES_DIR_NAME; 237 } 238 pathToFile(utility, utility.getResPath(), resPath, false); 239 } 240 241 if (!utility.getResourcesPath().isEmpty() && !utility.getModuleName().isEmpty()) { 242 String resourcesPath = ASSETS_DIR_NAME + utility.getModuleName() + LINUX_FILE_SEPARATOR 243 + RESOURCES_DIR_NAME; 244 pathToFile(utility, utility.getResourcesPath(), resourcesPath, false); 245 } 246 247 if (!utility.getRpcidPath().isEmpty()) { 248 String rpcidPath = NULL_DIR_NAME; 249 pathToFile(utility, utility.getRpcidPath(), rpcidPath, false); 250 } 251 252 if (!utility.getAssetsPath().isEmpty()) { 253 pathToFile(utility, utility.getAssetsPath(), ASSETS_DIR_NAME, false); 254 } 255 256 if (!utility.getBinPath().isEmpty()) { 257 pathToFile(utility, utility.getBinPath(), NULL_DIR_NAME, false); 258 } 259 260 if (!utility.getPackInfoPath().isEmpty()) { 261 pathToFile(utility, utility.getPackInfoPath(), NULL_DIR_NAME, false); 262 } 263 compressHapModeMultiple(utility); 264 } 265 266 /** 267 * compress in hap mode for module.json. 268 * 269 * @param utility common data 270 * @throws BundleException FileNotFoundException|IOException. 271 */ compressHapModeForModule(Utility utility)272 private void compressHapModeForModule(Utility utility) throws BundleException { 273 pathToFile(utility, utility.getJsonPath(), NULL_DIR_NAME, false); 274 275 pathToFile(utility, utility.getProfilePath(), NULL_DIR_NAME, false); 276 277 if (!utility.getIndexPath().isEmpty() && isModuleJSON(utility.getJsonPath())) { 278 String assetsPath = NULL_DIR_NAME; 279 pathToFile(utility, utility.getIndexPath(), assetsPath, false); 280 } 281 282 if (!utility.getLibPath().isEmpty()) { 283 pathToFile(utility, utility.getLibPath(), LIBS_DIR_NAME, utility.isCompressNativeLibs()); 284 } 285 286 if (!utility.getFilePath().isEmpty()) { 287 pathToFile(utility, utility.getFilePath(), NULL_DIR_NAME, false); 288 } 289 290 if (!utility.getResPath().isEmpty() && !utility.getModuleName().isEmpty()) { 291 String resPath = ASSETS_DIR_NAME + utility.getModuleName() + LINUX_FILE_SEPARATOR 292 + RESOURCES_DIR_NAME; 293 if (DEVICE_TYPE_FITNESSWATCH.equals(utility.getDeviceType().replace("\"", "").trim()) || 294 DEVICE_TYPE_FITNESSWATCH_NEW.equals(utility.getDeviceType().replace("\"", "").trim())) { 295 resPath = RES_DIR_NAME; 296 } 297 pathToFile(utility, utility.getResPath(), resPath, false); 298 } 299 300 if (!utility.getResourcesPath().isEmpty() && isModuleJSON(utility.getJsonPath())) { 301 String resourcesPath = RESOURCES_DIR_NAME; 302 pathToFile(utility, utility.getResourcesPath(), resourcesPath, false); 303 } 304 if (!utility.getJsPath().isEmpty() && isModuleJSON(utility.getJsonPath())) { 305 String jsPath = JS_PATH; 306 pathToFile(utility, utility.getJsPath(), jsPath, false); 307 } 308 309 if (!utility.getEtsPath().isEmpty() && isModuleJSON(utility.getJsonPath())) { 310 String etsPath = ETS_PATH; 311 pathToFile(utility, utility.getEtsPath(), etsPath, false); 312 } 313 314 if (!utility.getRpcidPath().isEmpty()) { 315 String rpcidPath = NULL_DIR_NAME; 316 pathToFile(utility, utility.getRpcidPath(), rpcidPath, false); 317 } 318 319 if (!utility.getAssetsPath().isEmpty()) { 320 pathToFile(utility, utility.getAssetsPath(), ASSETS_DIR_NAME, false); 321 } 322 323 if (!utility.getBinPath().isEmpty()) { 324 pathToFile(utility, utility.getBinPath(), NULL_DIR_NAME, false); 325 } 326 327 if (!utility.getPackInfoPath().isEmpty()) { 328 pathToFile(utility, utility.getPackInfoPath(), NULL_DIR_NAME, false); 329 } 330 compressHapModeMultiple(utility); 331 } 332 333 /** 334 * compress in hap mode multiple path. 335 * 336 * @param utility common data 337 * @throws BundleException FileNotFoundException|IOException. 338 */ compressHapModeMultiple(Utility utility)339 private void compressHapModeMultiple(Utility utility) throws BundleException { 340 for (String soPathItem : utility.getFormattedSoPathList()) { 341 pathToFile(utility, soPathItem, SO_ARM64_DIR_NAME, false); 342 } 343 344 if (utility.getFormattedSoPathList().size() == 0 && !utility.getSoDir().isEmpty()) { 345 pathToFile(utility, utility.getSoDir(), SO_DIR_NAME, false); 346 } 347 348 for (String soPathItem : utility.getFormattedAbilitySoPathList()) { 349 pathToFile(utility, soPathItem, NULL_DIR_NAME, false); 350 } 351 352 for (String dexPathItem : utility.getFormattedDexPathList()) { 353 pathToFile(utility, dexPathItem, NULL_DIR_NAME, false); 354 } 355 356 for (String abcPathItem : utility.getFormattedAbcPathList()) { 357 pathToFile(utility, abcPathItem, NULL_DIR_NAME, false); 358 } 359 360 for (String apkPathItem : utility.getFormattedApkPathList()) { 361 pathToFile(utility, apkPathItem, NULL_DIR_NAME, false); 362 } 363 364 for (String jarPathItem : utility.getFormattedJarPathList()) { 365 pathToFile(utility, jarPathItem, NULL_DIR_NAME, false); 366 } 367 368 for (String txtPathItem : utility.getFormattedTxtPathList()) { 369 pathToFile(utility, txtPathItem, NULL_DIR_NAME, false); 370 } 371 372 if (!utility.getSharedLibsPath().isEmpty()) { 373 pathToFile(utility, utility.getSharedLibsPath(), SHARED_LIBS_DIR_NAME, utility.isCompressNativeLibs()); 374 } 375 } 376 377 /** 378 * compress in har mode. 379 * 380 * @param utility common data 381 * @throws BundleException FileNotFoundException|IOException. 382 */ compressHarMode(Utility utility)383 private void compressHarMode(Utility utility) throws BundleException { 384 pathToFile(utility, utility.getJsonPath(), NULL_DIR_NAME, false); 385 386 if (!utility.getLibPath().isEmpty()) { 387 pathToFile(utility, utility.getLibPath(), LIBS_DIR_NAME, utility.isCompressNativeLibs()); 388 } 389 390 if (!utility.getResPath().isEmpty()) { 391 pathToFile(utility, utility.getResPath(), RESOURCES_DIR_NAME, false); 392 } 393 394 if (!utility.getResourcesPath().isEmpty()) { 395 pathToFile(utility, utility.getResourcesPath(), RESOURCES_DIR_NAME, false); 396 } 397 398 if (!utility.getAssetsPath().isEmpty()) { 399 pathToFile(utility, utility.getAssetsPath(), ASSETS_DIR_NAME, false); 400 } 401 402 for (String jarPathItem : utility.getFormattedJarPathList()) { 403 pathToFile(utility, jarPathItem, NULL_DIR_NAME, false); 404 } 405 406 for (String txtPathItem : utility.getFormattedTxtPathList()) { 407 pathToFile(utility, txtPathItem, NULL_DIR_NAME, false); 408 } 409 } 410 411 /** 412 * compress in app mode. 413 * 414 * @param utility common data 415 * @throws BundleException FileNotFoundException|IOException. 416 */ compressAppMode(Utility utility)417 private void compressAppMode(Utility utility) throws BundleException { 418 pathToFile(utility, utility.getJsonPath(), NULL_DIR_NAME, false); 419 420 if (!utility.getCertificatePath().isEmpty()) { 421 pathToFile(utility, utility.getCertificatePath(), NULL_DIR_NAME, false); 422 } 423 424 if (!utility.getSignaturePath().isEmpty()) { 425 pathToFile(utility, utility.getSignaturePath(), NULL_DIR_NAME, false); 426 } 427 428 File appOutputFile = new File(utility.getOutPath().trim()); 429 List<String> fileList = new ArrayList<>(); 430 for (String hapPathItem : utility.getFormattedHapPathList()) { 431 File hapFile = new File(hapPathItem.trim()); 432 String hapTempPath = appOutputFile.getParentFile().getParent() + File.separator + hapFile.getName(); 433 fileList.add(hapTempPath); 434 try { 435 compressPackinfoIntoHap(hapPathItem, hapTempPath, utility.getPackInfoPath()); 436 } catch ( IOException e) { 437 LOG.error("Compressor::compressAppMode compress pack.info into hap failed"); 438 throw new BundleException("Compressor::compressAppMode compress pack.info into hap failed"); 439 } 440 } 441 for (String hapPath : fileList) { 442 pathToFile(utility, hapPath, NULL_DIR_NAME, false); 443 } 444 445 for (String hapPath : fileList) { 446 deleteFile(hapPath); 447 } 448 449 if (!utility.getEntryCardPath().isEmpty()) { 450 String entryCardPath = ENTRYCARD_NAME + utility.getModuleName() + LINUX_FILE_SEPARATOR 451 + ENTRYCARD_BASE_NAME + ENTRYCARD_SNAPSHOT_NAME; 452 for (String entryCardPathItem : utility.getformattedEntryCardPathList()) { 453 pathToFile(utility, entryCardPathItem, entryCardPath, true); 454 } 455 } 456 457 if (!utility.getPackResPath().isEmpty()) { 458 pathToFile(utility, utility.getPackResPath(), NULL_DIR_NAME, false); 459 } 460 File file = new File(utility.getPackInfoPath()); 461 compressFile(utility, file, NULL_DIR_NAME, false); 462 } 463 copy(InputStream input, OutputStream output)464 private void copy(InputStream input, OutputStream output) throws IOException { 465 int bytesRead; 466 byte[] data = new byte[BUFFER_SIZE]; 467 while ((bytesRead = input.read(data, 0, BUFFER_SIZE)) != -1) { 468 output.write(data, 0, bytesRead); 469 } 470 } 471 compressPackinfoIntoHap(String hapPathItem, String outPathString, String packInfo)472 private void compressPackinfoIntoHap(String hapPathItem, String outPathString, String packInfo) 473 throws FileNotFoundException, IOException, BundleException { 474 ZipFile sourceHapFile = new ZipFile(hapPathItem); 475 ZipOutputStream append = new ZipOutputStream(new FileOutputStream(outPathString)); 476 try { 477 Enumeration<? extends ZipEntry> entries = sourceHapFile.entries(); 478 while (entries.hasMoreElements()) { 479 ZipEntry zipEntry = entries.nextElement(); 480 if (zipEntry.getName() != null && PACKINFO_NAME.equals(zipEntry.getName())) { 481 continue; 482 } 483 append.putNextEntry(zipEntry); 484 if (!zipEntry.isDirectory()) { 485 copy(sourceHapFile.getInputStream(zipEntry), append); 486 } 487 append.closeEntry(); 488 } 489 File packInfoFile = new File(packInfo); 490 ZipEntry zipEntry = getStoredZipEntry(packInfoFile, PACKINFO_NAME); 491 append.putNextEntry(zipEntry); 492 FileInputStream in = new FileInputStream(packInfoFile); 493 try { 494 byte[] buf = new byte[BUFFER_SIZE]; 495 int len; 496 while ((len = in.read(buf)) != -1) { 497 append.write(buf, 0, len); 498 } 499 } finally { 500 in.close(); 501 } 502 append.closeEntry(); 503 } catch (IOException exception) { 504 LOG.error("Compressor::compressPackinfoIntoHap io exception"); 505 throw new BundleException("Compressor::compressPackinfoIntoHap io exception"); 506 } finally { 507 sourceHapFile.close(); 508 append.close(); 509 } 510 } 511 512 /** 513 * zipFile 514 * 515 * @param utility Utility 516 * @param path path 517 * @param format destFileName 518 */ zipFile(String path)519 private void zipFile(String path) { 520 FileOutputStream outputStream = null; 521 ZipOutputStream out = null; 522 try { 523 File destFile = new File(path + HAP_SUFFIX); 524 File outParentFile = destFile.getParentFile(); 525 if ((outParentFile != null) && (!outParentFile.exists())) { 526 if (!outParentFile.mkdirs()) { 527 LOG.error("Compressor::compressProcess create out file parent directory failed!"); 528 } 529 } 530 outputStream = new FileOutputStream(destFile); 531 out = new ZipOutputStream(new CheckedOutputStream(outputStream, new CRC32())); 532 out.setMethod(ZipOutputStream.STORED); 533 compress(new File(path), out, NULL_DIR_NAME, true); 534 } catch (FileNotFoundException ignored) { 535 LOG.error("zip file not found exception"); 536 } finally { 537 Utility.closeStream(out); 538 Utility.closeStream(outputStream); 539 deleteFile(path); 540 } 541 } 542 543 /** 544 * copyFileUsingFileStreams pack.info 545 * 546 * @param source inputPath 547 * @param dest outputPath 548 * 549 */ copyFileUsingFileStreams(String source, String dest)550 private static void copyFileUsingFileStreams(String source, String dest) { 551 FileInputStream input = null; 552 FileOutputStream output = null; 553 try { 554 File inputFile = new File(source); 555 File outputFile = new File(dest, PACKINFO_NAME); 556 File outputFileParent = outputFile.getParentFile(); 557 if (!outputFileParent.exists()) { 558 outputFileParent.mkdirs(); 559 } 560 if (!outputFile.exists()) { 561 outputFile.createNewFile(); 562 } 563 input = new FileInputStream(inputFile); 564 output = new FileOutputStream(outputFile); 565 byte[] buf = new byte[1024]; 566 int bytesRead; 567 while ((bytesRead = input.read(buf)) != -1) { 568 output.write(buf, 0, bytesRead); 569 } 570 input.close(); 571 output.close(); 572 } catch (FileNotFoundException ignored) { 573 LOG.error("copy file not found exception" + ignored.toString()); 574 } catch (IOException msg) { 575 LOG.error("IOException : " + msg.getMessage()); 576 } finally { 577 Utility.closeStream(input); 578 Utility.closeStream(output); 579 } 580 } 581 582 583 /** 584 * unzip hap package to path 585 * 586 * @param hapPath zip file 587 * @param destDir path after unzip file 588 */ unzip(final String hapPath, final String destDir)589 public static void unzip(final String hapPath, final String destDir) { 590 File file = new File(destDir); 591 if (!file.exists()) { 592 file.mkdirs(); 593 } 594 ZipFile zipFile = null; 595 BufferedInputStream bis = null; 596 BufferedOutputStream bos = null; 597 FileOutputStream fos = null; 598 try { 599 zipFile = new ZipFile(hapPath); 600 Enumeration<? extends ZipEntry> entries = zipFile.entries(); 601 int entriesNum = 0; 602 while (entries.hasMoreElements()) { 603 entriesNum++; 604 ZipEntry entry = entries.nextElement(); 605 if (entry == null) { 606 continue; 607 } 608 if (entry.isDirectory()) { 609 new File(destDir + File.separator + entry.getName()).mkdirs(); 610 continue; 611 } 612 bis = new BufferedInputStream(zipFile.getInputStream(entry)); 613 File newFile = new File(destDir + File.separator + entry.getName()); 614 File parent = newFile.getParentFile(); 615 if (parent != null && (!parent.exists())) { 616 parent.mkdirs(); 617 } 618 fos = new FileOutputStream(newFile); 619 bos = new BufferedOutputStream(fos, BUFFER_SIZE); 620 writeFile(bis, bos, entry); 621 bos.flush(); 622 bos.close(); 623 fos.close(); 624 bis.close(); 625 } 626 } catch (FileNotFoundException ignored) { 627 LOG.error("unzip file not found exception"); 628 } catch (IOException msg) { 629 LOG.error("unzip IOException : " + msg.getMessage()); 630 } finally { 631 Utility.closeStream(bos); 632 Utility.closeStream(fos); 633 Utility.closeStream(bis); 634 Utility.closeStream(zipFile); 635 } 636 } 637 638 /** 639 * unzipWriteFile 640 * 641 * @param bis BufferedInputStream 642 * @param bos BufferedOutputStream 643 * @param entry ZipEntry 644 * @throws IOException IO 645 */ writeFile(BufferedInputStream bis, BufferedOutputStream bos, ZipEntry entry)646 private static void writeFile(BufferedInputStream bis, BufferedOutputStream bos, 647 ZipEntry entry) throws IOException { 648 int count; 649 int total = 0; 650 byte[] data = new byte[BUFFER_SIZE]; 651 while ((count = bis.read(data, 0, BUFFER_SIZE)) != -1) { 652 bos.write(data, 0, count); 653 total += count; 654 } 655 } 656 657 /** 658 * delete file 659 * 660 * @param path file path which will be deleted 661 */ deleteFile(final String path)662 private static void deleteFile(final String path) { 663 File file = new File(path); 664 if (file.exists()) { 665 if (file.isDirectory()) { 666 File[] files = file.listFiles(); 667 for (int i = 0; i < files.length; i++) { 668 deleteFile(files[i].toString()); 669 } 670 } 671 file.delete(); 672 } 673 } 674 675 /** 676 * compress in res mode. 677 * 678 * @param utility common data 679 * @throws BundleException FileNotFoundException|IOException. 680 */ compressPackResMode(Utility utility)681 private void compressPackResMode(Utility utility) throws BundleException { 682 if (!utility.getPackInfoPath().isEmpty()) { 683 File file = new File(utility.getPackInfoPath()); 684 infoSpecialProcess(utility, file); 685 } 686 if (!utility.getEntryCardPath().isEmpty()) { 687 getFileList(utility.getEntryCardPath()); 688 if (!mIsContain2x2EntryCard) { 689 LOG.error("Compressor::compressPackResMode No 2x2 resource file exists"); 690 throw new BundleException("No 2x2 resource file exists"); 691 } 692 for (String fileName : fileNameList) { 693 if (fileName.endsWith(PNG_SUFFIX) || fileName.endsWith(UPPERCASE_PNG_SUFFIX)) { 694 String fName = fileName.trim(); 695 String[] temp = fName.replace("\\", "/").split("/"); 696 if (temp.length < 4) { 697 LOG.error("Compressor::compressPackResMode the hap file path is invalid, length: " 698 + temp.length); 699 continue; 700 } 701 String moduleName = temp[temp.length - 4]; 702 if (!isModelName(moduleName)) { 703 LOG.error("Compressor::compressProcess compress pack.res failed, moduleName " 704 + moduleName + " is error, please check it in config.json"); 705 throw new BundleException("Compress pack.res failed, moduleName Error"); 706 } 707 String fileLanguageCountryName = temp[temp.length - 3]; 708 if (!isThirdLevelDirectoryNameValid(fileLanguageCountryName)) { 709 LOG.error("Compressor::compressProcess compress failed third level directory name: " 710 + fileLanguageCountryName + " is invalid, please check it with reference to this example: " 711 + "zh_Hani_CN-vertical-car-mdpi-dark or zh_Hani_CN-vertical-car-mdpi"); 712 throw new BundleException("Compress failed third level directory name Error!"); 713 } 714 String filePicturingName = temp[temp.length - 1]; 715 if (!isPicturing(filePicturingName, utility)) { 716 LOG.error("Compressor::compressProcess Compress pack.res failed, Invalid resource file" + 717 " name: " + filePicturingName + ", correct format example is formName-2x2.png"); 718 throw new BundleException("Compress pack.res failed, Invalid resource file name: " 719 + filePicturingName + ", correct format example is formName-2x2.png"); 720 } 721 722 } else { 723 LOG.error("Compressor::compressProcess compress failed No image in PNG format is found!"); 724 throw new BundleException("Compress pack.res failed, compress failed No image in" 725 + " PNG format is found"); 726 } 727 } 728 pathToFile(utility, utility.getEntryCardPath(), ENTRYCARD_NAME, false); 729 } 730 } 731 732 /** 733 * Check whether modelname meets specifications. 734 * 735 * @param name modelName 736 * @return false and true 737 */ isModelName(String name)738 private boolean isModelName(String name) { 739 for (String listName : list) { 740 if (name.equals(listName)) { 741 return true; 742 } 743 } 744 return false; 745 } 746 isThirdLevelDirectoryNameValid(String thirdLevelDirectoryName)747 private boolean isThirdLevelDirectoryNameValid(String thirdLevelDirectoryName) { 748 if (thirdLevelDirectoryName == null || thirdLevelDirectoryName.isEmpty()) { 749 return false; 750 } 751 if (ENTRYCARD_BASE_NAME.equals(thirdLevelDirectoryName)) { 752 return true; 753 } 754 // example: zh_Hani_CN-vertical-car-mdpi-dark or zh_Hani_CN-vertical-car-mdpi 755 int firstDelimiterIndex = thirdLevelDirectoryName.indexOf("_"); 756 if (firstDelimiterIndex < 0) { 757 return false; 758 } 759 String language = thirdLevelDirectoryName.substring(0, firstDelimiterIndex); 760 int secondDelimiterIndex = thirdLevelDirectoryName.indexOf("_", firstDelimiterIndex + 1); 761 if (secondDelimiterIndex < 0) { 762 return false; 763 } 764 String script = thirdLevelDirectoryName.substring(firstDelimiterIndex + 1, secondDelimiterIndex); 765 int thirdDelimiterIndex = thirdLevelDirectoryName.indexOf("-", secondDelimiterIndex + 1); 766 if (thirdDelimiterIndex < 0) { 767 return false; 768 } 769 String country = thirdLevelDirectoryName.substring(secondDelimiterIndex + 1, thirdDelimiterIndex); 770 if (!checkLanguage(language) || !checkScript(script) || !checkCountry(country)) { 771 return false; 772 } 773 int forthDelimiterIndex = thirdLevelDirectoryName.indexOf("-", thirdDelimiterIndex + 1); 774 if (forthDelimiterIndex < 0) { 775 return false; 776 } 777 String orientation = thirdLevelDirectoryName.substring(thirdDelimiterIndex + 1, forthDelimiterIndex); 778 int fifthDelimiterIndex = thirdLevelDirectoryName.indexOf("-", forthDelimiterIndex + 1); 779 if (fifthDelimiterIndex < 0) { 780 return false; 781 } 782 String deviceType = thirdLevelDirectoryName.substring(forthDelimiterIndex + 1, fifthDelimiterIndex); 783 if (!checkOrientation(orientation) || !checkDeviceType(deviceType)) { 784 return false; 785 } 786 int sixthDelimiterIndex = thirdLevelDirectoryName.indexOf("-", fifthDelimiterIndex + 1); 787 if (sixthDelimiterIndex < 0) { 788 String screenDensity = thirdLevelDirectoryName.substring(fifthDelimiterIndex + 1, 789 thirdLevelDirectoryName.length()); 790 return checkScreenDensity(screenDensity); 791 } else { 792 String screenDensity = thirdLevelDirectoryName.substring(fifthDelimiterIndex + 1, sixthDelimiterIndex); 793 if (!checkScreenDensity(screenDensity)) { 794 return false; 795 } 796 } 797 int seventhDelimiterIndex = thirdLevelDirectoryName.indexOf("-", sixthDelimiterIndex + 1); 798 if (seventhDelimiterIndex < 0) { 799 String tmp = thirdLevelDirectoryName.substring(sixthDelimiterIndex + 1, thirdLevelDirectoryName.length()); 800 return checkColorModeOrShape(tmp); 801 } 802 if (!checkColorMode(thirdLevelDirectoryName.substring(sixthDelimiterIndex + 1, seventhDelimiterIndex))) { 803 return false; 804 } 805 String shape = thirdLevelDirectoryName.substring(seventhDelimiterIndex + 1, thirdLevelDirectoryName.length()); 806 return checkShape(shape); 807 } 808 checkLanguage(String language)809 private boolean checkLanguage(String language) { 810 if (!Pattern.compile(REGEX_LANGUAGE).matcher(language).matches()) { 811 LOG.error("Compressor::compressProcess language " + language + " is not in ISO 639-1 list"); 812 return false; 813 } 814 return true; 815 } 816 checkScript(String script)817 private boolean checkScript(String script) { 818 if (!Pattern.compile(REGEX_SCRIPT).matcher(script).matches()) { 819 LOG.error("Compressor::compressProcess script " + script + " is not in ISO 15924 list"); 820 return false; 821 } 822 return true; 823 } 824 checkCountry(String country)825 private boolean checkCountry(String country) { 826 if (!Pattern.compile(REGEX_COUNTRY).matcher(country).matches()) { 827 LOG.error("Compressor::compressProcess country " + country + " is not in ISO 3166-1 list"); 828 return false; 829 } 830 return true; 831 } 832 checkOrientation(String orientation)833 private boolean checkOrientation(String orientation) { 834 if (!Pattern.compile(REGEX_ORIENTATION).matcher(orientation).matches()) { 835 LOG.error("Compressor::compressProcess orientation " + orientation + 836 " is not in {vertical, horizontal} list"); 837 return false; 838 } 839 return true; 840 } 841 checkDeviceType(String deviceType)842 private boolean checkDeviceType(String deviceType) { 843 if (!Pattern.compile(REGEX_DEVICE_TYPE).matcher(deviceType).matches()) { 844 LOG.error("Compressor::compressProcess deviceType " + deviceType + 845 " is not in {phone, tablet, car, tv, wearable, liteWearable} list"); 846 return false; 847 } 848 return true; 849 } 850 checkScreenDensity(String screenDensity)851 private boolean checkScreenDensity(String screenDensity) { 852 if (!Pattern.compile(REGEX_SCREEN_DENSITY).matcher(screenDensity).matches()) { 853 LOG.error("Compressor::compressProcess screenDensity " + screenDensity + 854 " is not in {sdpi, mdpi, ldpi, xldpi, xxldpi} list"); 855 return false; 856 } 857 return true; 858 } 859 checkColorMode(String colorMode)860 private boolean checkColorMode(String colorMode) { 861 if (!Pattern.compile(REGEX_COLOR_MODE).matcher(colorMode).matches()) { 862 LOG.error("Compressor::compressProcess colorMode " + colorMode + 863 " is not in {light, dark} list"); 864 return false; 865 } 866 return true; 867 } 868 checkColorModeOrShape(String tmp)869 private boolean checkColorModeOrShape(String tmp) { 870 if (Pattern.compile(REGEX_COLOR_MODE).matcher(tmp).matches() || 871 Pattern.compile(REGEX_SHAPE).matcher(tmp).matches()) { 872 return true; 873 } 874 LOG.error("Compressor::compressProcess " + tmp + 875 " is neither in colorMode list {light, dark} nor in shape list {circle}"); 876 return false; 877 } 878 checkShape(String shape)879 private boolean checkShape(String shape) { 880 if (Pattern.compile(REGEX_SHAPE).matcher(shape).matches()) { 881 return true; 882 } 883 LOG.error("Compressor::compressProcess shape" + shape + " is not in {circle} list"); 884 return false; 885 } 886 887 /** 888 * Check whether languageCountryName meets specifications. 889 * 890 * @param name languageCountryName 891 * @return false and true 892 */ isLanguageCountry(String name)893 private boolean isLanguageCountry(String name) { 894 if (!name.equals(ENTRYCARD_BASE_NAME)) { 895 boolean isLanguage = false; 896 String[] str = name.split("-"); 897 if (str.length > 1) { 898 Locale[] ls = Locale.getAvailableLocales(); 899 for (int i = 0; i < ls.length; i++) { 900 if (ls[i].toString().equals(str[0])) { 901 isLanguage = true; 902 } 903 } 904 if (str[1].equals( VERTICAL ) || str[1].equals( HORIZONTAL )) { 905 isLanguage = true; 906 } 907 if (str[2].equals( CAR ) || str[2].equals( TV ) || str[2].equals( WEARABLE )) { 908 isLanguage = true; 909 } 910 if (str[3].equals( SDIP ) || str[3].equals( MDIP )) { 911 isLanguage = true; 912 } 913 return isLanguage; 914 } else { 915 return false; 916 } 917 } else { 918 return true; 919 } 920 } 921 922 /** 923 * Check whether picturingName meets specifications. 924 * 925 * @param name picturingName 926 * @param utility common data 927 * @return false and true 928 */ isPicturing(String name, Utility utility)929 private boolean isPicturing(String name, Utility utility) { 930 boolean isSpecifications = false; 931 if (name == null || name.isEmpty()) { 932 return isSpecifications; 933 } 934 if (!name.endsWith(PNG_SUFFIX) && !name.endsWith(UPPERCASE_PNG_SUFFIX)) { 935 LOG.error("isPicturing: the suffix is not .png or .PNG"); 936 return false; 937 } 938 int delimiterIndex = name.lastIndexOf("-"); 939 if (delimiterIndex < 0) { 940 LOG.error("isPicturing: the entry card naming format is invalid and should be separated by '-'!"); 941 return false; 942 } 943 String formName = name.substring(0, delimiterIndex); 944 if (!utility.getFormNameList().contains(formName)) { 945 LOG.error("isPicturing: the name is not same as formName, name: " + formName + " is not in " + 946 utility.getFormNameList().toString()); 947 return false; 948 } 949 String dimension = name.substring(delimiterIndex + 1, name.lastIndexOf(".")); 950 if (!supportDimensionsList.contains(dimension)) { 951 LOG.error("isPicturing: the dimension: " + dimension + " is invalid, is not in the following list: " 952 + "{1X2, 2X2, 2X4, 4X4}"); 953 return false; 954 } 955 return true; 956 } 957 getFileList(final String filePath)958 private void getFileList(final String filePath) throws BundleException { 959 File file = new File(filePath); 960 if (!file.exists()) { 961 LOG.error("getFileList: file is not exists"); 962 return; 963 } 964 File[] files = file.listFiles(); 965 if (files == null) { 966 LOG.error("getFileList: no file in this file path"); 967 return; 968 } 969 for (File f : files) { 970 try { 971 if (f.isFile()) { 972 if (f.getName().endsWith(".DS_Store")) { 973 deleteFile(f.getCanonicalPath()); 974 continue; 975 } 976 String snapshotDirectoryName = f.getParentFile().getName(); 977 if (!ENTRYCARD_SNAPSHOT_NAME.equals(snapshotDirectoryName)) { 978 LOG.error("The level-4 directory of EntryCard must be named as snapshot" + 979 ", but current is: " + snapshotDirectoryName); 980 throw new BundleException("The level-4 directory of EntryCard must be named as snapshot" + 981 ", but current is: " + snapshotDirectoryName); 982 } 983 checkContain2x2EntryCard(f.getParentFile()); 984 fileNameList.add(f.getCanonicalPath()); 985 } else if (f.isDirectory()) { 986 getFileList(f.getCanonicalPath()); 987 } else { 988 LOG.error("It's not file or directory!"); 989 } 990 } catch (IOException msg) { 991 LOG.error("IOException error: " + msg.getMessage()); 992 return; 993 } 994 } 995 } 996 checkContain2x2EntryCard(final File snapshotDirectory)997 private void checkContain2x2EntryCard(final File snapshotDirectory) throws IOException, BundleException { 998 if (!snapshotDirectory.exists()) { 999 LOG.error("checkContain2x2EntryCard: file is not exist: " + snapshotDirectory.getName()); 1000 throw new BundleException("checkContain2x2EntryCard: file is not exist"); 1001 } 1002 File[] files = snapshotDirectory.listFiles(); 1003 if (files == null) { 1004 LOG.error("checkContain2x2EntryCard: no file in this file path"); 1005 throw new BundleException("checkContain2x2EntryCard: no file in this file path"); 1006 } 1007 1008 for (File entryCardFile : files) { 1009 if (entryCardFile.isFile() && entryCardFile.getName().contains(PIC_2X2)) { 1010 return; 1011 } 1012 } 1013 mIsContain2x2EntryCard = false; 1014 LOG.error("checkContain2x2EntryCard: must contain 2x2 entryCard, please check it in " 1015 + snapshotDirectory.getCanonicalPath()); 1016 throw new BundleException("checkContain2x2EntryCard: must contain 2x2 entryCard, please check it in " 1017 + snapshotDirectory.getCanonicalPath()); 1018 } 1019 1020 /** 1021 * compress file or directory. 1022 * 1023 * @param utility common data 1024 * @param path create new file by path 1025 * @param baseDir base path for file 1026 * @param isCompression if need compression 1027 * @throws BundleException FileNotFoundException|IOException. 1028 */ pathToFile(Utility utility, String path, String baseDir, boolean isCompression)1029 private void pathToFile(Utility utility, String path, String baseDir, boolean isCompression) 1030 throws BundleException { 1031 if (path.isEmpty()) { 1032 return; 1033 } 1034 File fileItem = new File(path); 1035 if (fileItem.isDirectory()) { 1036 File[] files = fileItem.listFiles(); 1037 if (files == null) { 1038 return; 1039 } 1040 for (File file : files) { 1041 if (file.isDirectory()) { 1042 compressDirectory(utility, file, baseDir, isCompression); 1043 } else if (isCompression) { 1044 compressFile(utility, file, baseDir, isCompression); 1045 } else { 1046 compressFile(utility, file, baseDir, isCompression); 1047 } 1048 } 1049 } else { 1050 compressFile(utility, fileItem, baseDir, isCompression); 1051 } 1052 } 1053 1054 /** 1055 * compress file directory. 1056 * 1057 * @param utility common data 1058 * @param dir file directory 1059 * @param baseDir current directory name 1060 * @param isCompression if need compression 1061 * @throws BundleException FileNotFoundException|IOException. 1062 */ compressDirectory(Utility utility, File dir, String baseDir, boolean isCompression)1063 private void compressDirectory(Utility utility, File dir, String baseDir, boolean isCompression) 1064 throws BundleException { 1065 File[] files = dir.listFiles(); 1066 if (files == null) { 1067 return; 1068 } 1069 for (File file : files) { 1070 if (file.isDirectory()) { 1071 compressDirectory(utility, file, baseDir + dir.getName() + File.separator, isCompression); 1072 } else { 1073 compressFile(utility, file, baseDir + dir.getName() + File.separator, isCompression); 1074 } 1075 } 1076 } 1077 1078 /** 1079 * compress pack.info 1080 * 1081 * @param sourceFile source 1082 * @param zipOutputStream ZipOutputStream 1083 * @param name filename 1084 * @param KeepDirStructure Empty File 1085 */ compress(File sourceFile, ZipOutputStream zipOutputStream, String name, boolean KeepDirStructure)1086 private void compress(File sourceFile, ZipOutputStream zipOutputStream, String name, 1087 boolean KeepDirStructure) { 1088 FileInputStream in = null; 1089 try { 1090 byte[] buf = new byte[BUFFER_SIZE]; 1091 if (sourceFile.isFile()) { 1092 ZipEntry zipEntry = getStoredZipEntry(sourceFile, name); 1093 zipOutputStream.putNextEntry(zipEntry); 1094 in = new FileInputStream(sourceFile); 1095 int len; 1096 while ((len = in.read(buf)) != -1) { 1097 zipOutputStream.write(buf, 0, len); 1098 } 1099 zipOutputStream.closeEntry(); 1100 } else { 1101 File[] listFiles = sourceFile.listFiles(); 1102 if (listFiles == null || listFiles.length == 0) { 1103 if (KeepDirStructure) { 1104 if (!name.isEmpty()) { 1105 ZipEntry zipEntry = getStoredZipEntry(sourceFile, name + "/"); 1106 zipOutputStream.putNextEntry(zipEntry); 1107 } else { 1108 ZipEntry zipEntry = getStoredZipEntry(sourceFile, name); 1109 zipOutputStream.putNextEntry(zipEntry); 1110 } 1111 zipOutputStream.closeEntry(); 1112 } 1113 } else { 1114 for (File file : listFiles) { 1115 if (KeepDirStructure) { 1116 isNameEmpty(zipOutputStream, name, KeepDirStructure, file); 1117 } else { 1118 compress(file, zipOutputStream, file.getName(), KeepDirStructure); 1119 } 1120 } 1121 } 1122 } 1123 } catch (FileNotFoundException ignored) { 1124 LOG.error("Compressor::compressFile file not found exception"); 1125 } catch (IOException exception) { 1126 LOG.error("Compressor::compressFile io exception: " + exception.getMessage()); 1127 } catch (BundleException bundleException) { 1128 LOG.error("Compressor::compressFile bundle exception" + bundleException.getMessage()); 1129 } finally { 1130 Utility.closeStream(in); 1131 } 1132 } 1133 getStoredZipEntry(File sourceFile, String name)1134 private ZipEntry getStoredZipEntry(File sourceFile, String name) throws BundleException { 1135 ZipEntry zipEntry = new ZipEntry(name); 1136 zipEntry.setMethod(ZipEntry.STORED); 1137 zipEntry.setCompressedSize(sourceFile.length()); 1138 zipEntry.setSize(sourceFile.length()); 1139 CRC32 crc = getCrcFromFile(sourceFile); 1140 zipEntry.setCrc(crc.getValue()); 1141 FileTime fileTime = FileTime.fromMillis(FILE_TIME); 1142 zipEntry.setLastAccessTime(fileTime); 1143 zipEntry.setLastModifiedTime(fileTime); 1144 return zipEntry; 1145 } 1146 getCrcFromFile(File file)1147 private CRC32 getCrcFromFile(File file) throws BundleException { 1148 FileInputStream fileInputStream = null; 1149 CRC32 crc = new CRC32(); 1150 try { 1151 fileInputStream = new FileInputStream(file); 1152 byte[] buffer = new byte[BUFFER_SIZE]; 1153 1154 int count = fileInputStream.read(buffer); 1155 while (count > 0) { 1156 crc.update(buffer, 0, count); 1157 count = fileInputStream.read(buffer); 1158 } 1159 } catch (FileNotFoundException ignored) { 1160 LOG.error("Uncompressor::getCrcFromFile file not found exception"); 1161 throw new BundleException("Get Crc from file failed"); 1162 } catch (IOException exception) { 1163 LOG.error("Uncompressor::getCrcFromFile io exception: " + exception.getMessage()); 1164 throw new BundleException("Get Crc from file failed"); 1165 } finally { 1166 Utility.closeStream(fileInputStream); 1167 } 1168 return crc; 1169 } 1170 1171 /** 1172 * isNameEmpty 1173 * 1174 * @param zipOutputStream ZipOutputStream 1175 * @param name filename 1176 * @param KeepDirStructure KeepDirStructure 1177 * @param file file 1178 */ isNameEmpty(ZipOutputStream zipOutputStream, String name, boolean KeepDirStructure, File file)1179 private void isNameEmpty(ZipOutputStream zipOutputStream, String name, boolean KeepDirStructure, File file) { 1180 if (!name.isEmpty()) { 1181 compress(file, zipOutputStream, name + "/" + file.getName(), KeepDirStructure); 1182 } else { 1183 compress(file, zipOutputStream, file.getName(), KeepDirStructure); 1184 } 1185 } 1186 1187 1188 /** 1189 * compress process. 1190 * 1191 * @param utility common data 1192 * @param srcFile source file to zip 1193 * @param baseDir current directory name of file 1194 * @param isCompression if need compression 1195 * @throws BundleException FileNotFoundException|IOException. 1196 */ compressFile(Utility utility, File srcFile, String baseDir, boolean isCompression)1197 private void compressFile(Utility utility, File srcFile, String baseDir, boolean isCompression) 1198 throws BundleException { 1199 BufferedInputStream bufferedInputStream = null; 1200 FileInputStream fileInputStream = null; 1201 try { 1202 String entryName = (baseDir + srcFile.getName()).replace(File.separator, LINUX_FILE_SEPARATOR); 1203 ZipEntry zipEntry = new ZipEntry(entryName); 1204 obtainModuleVersion(utility, srcFile, entryName); 1205 if (!utility.getIsModuleJson()) { 1206 if (!checkVersionInHaps(utility, srcFile, entryName)) { 1207 LOG.error("Compressor::compressFile file checkVersionCodeInHaps failed"); 1208 throw new BundleException("Compressor::compressFile There are some haps with different version code!"); 1209 } 1210 } 1211 if (srcFile.getName().toLowerCase(Locale.ENGLISH).endsWith(JSON_SUFFIX)) { 1212 zipEntry.setMethod(ZipEntry.STORED); 1213 jsonSpecialProcess(utility, srcFile, zipEntry); 1214 return; 1215 } 1216 1217 if (isCompression) { 1218 zipEntry.setMethod(ZipEntry.DEFLATED); 1219 } else { 1220 zipEntry.setMethod(ZipEntry.STORED); 1221 1222 // update size 1223 zipEntry.setCompressedSize(srcFile.length()); 1224 zipEntry.setSize(srcFile.length()); 1225 1226 // update crc 1227 CRC32 crc = getCrcFromFile(utility, srcFile); 1228 zipEntry.setCrc(crc.getValue()); 1229 } 1230 1231 // update fileTime 1232 FileTime fileTime = FileTime.fromMillis(FILE_TIME); 1233 zipEntry.setLastAccessTime(fileTime); 1234 zipEntry.setLastModifiedTime(fileTime); 1235 1236 zipOut.putNextEntry(zipEntry); 1237 byte[] data = new byte[BUFFER_SIZE]; 1238 fileInputStream = new FileInputStream(srcFile); 1239 bufferedInputStream = new BufferedInputStream(fileInputStream); 1240 1241 int count = bufferedInputStream.read(data); 1242 while (count > 0) { 1243 zipOut.write(data, 0, count); 1244 count = bufferedInputStream.read(data); 1245 } 1246 } catch (FileNotFoundException ignored) { 1247 LOG.error("Compressor::compressFile file not found exception"); 1248 throw new BundleException("CoompressFile failed"); 1249 } catch (IOException exception) { 1250 LOG.error("Compressor::compressFile io exception: " + exception.getMessage()); 1251 throw new BundleException("CoompressFile failed"); 1252 } finally { 1253 Utility.closeStream(bufferedInputStream); 1254 Utility.closeStream(fileInputStream); 1255 } 1256 } 1257 1258 /** 1259 * check json type code in haps. 1260 * 1261 * @param utility common data 1262 * @param srcFile source file to zip 1263 * @param baseDir current directory name of file 1264 * @return true is for successful and false is for failed 1265 * @throws BundleException FileNotFoundException|IOException. 1266 */ obtainModuleVersion(Utility utility, File srcFile, String baseDir)1267 private void obtainModuleVersion(Utility utility, File srcFile, String baseDir) throws BundleException { 1268 String moduleJson = ""; 1269 moduleJson = checkModuleTypeInHaps(utility, srcFile, baseDir); 1270 if (utility.getIsModuleJson() && !moduleJson.equals("")) { 1271 Version version = ModuleJsonUtil.getVersion(moduleJson); 1272 1273 if (utility.getVersionCode() == -1) { 1274 utility.setVersionCode(version.versionCode); 1275 } 1276 if (utility.getVersionName().equals("")) { 1277 utility.setVersionName(version.versionName); 1278 } 1279 if (!checkModuleVersion(utility, version)) { 1280 LOG.error("Compressor::checkModuleVersion failed "); 1281 throw new BundleException("Compressor::compressFile There are some haps with different version code!"); 1282 } 1283 } 1284 } 1285 1286 1287 /** 1288 * check version in haps. 1289 * 1290 * @param utility common data 1291 * @param version current hap version 1292 * @throws BundleException FileNotFoundException|IOException. 1293 */ checkModuleVersion(Utility utility, Version version)1294 private boolean checkModuleVersion(Utility utility, Version version) { 1295 if (version.versionName.equals("") || version.versionCode == -1) { 1296 return false; 1297 } 1298 if (!utility.getVersionName().equals(version.versionName)) { 1299 LOG.error("Compressor::checkModuleVersion versionName failed "); 1300 return false; 1301 } 1302 if (utility.getVersionCode() != version.versionCode) { 1303 LOG.error("Compressor::checkModuleVersion versionCode failed "); 1304 return false; 1305 } 1306 return true; 1307 } 1308 1309 /** 1310 * check json type code in haps. 1311 * 1312 * @param utility common data 1313 * @param srcFile source file to zip 1314 * @param baseDir current directory name of file 1315 * @return true is for successful and false is for failed 1316 * @throws BundleException FileNotFoundException|IOException. 1317 */ checkModuleTypeInHaps(Utility utility, File srcFile, String baseDir)1318 private String checkModuleTypeInHaps(Utility utility, File srcFile, String baseDir) throws BundleException { 1319 String fileStr = srcFile.getPath(); 1320 if (!fileStr.toLowerCase(Locale.ENGLISH).endsWith(HAP_SUFFIX)) { 1321 return ""; 1322 } 1323 ZipFile zipFile = null; 1324 FileInputStream zipInput = null; 1325 ZipInputStream zin = null; 1326 InputStream inputStream = null; 1327 InputStreamReader reader = null; 1328 BufferedReader br = null; 1329 ZipEntry entry = null; 1330 String moduleJson = ""; 1331 try { 1332 zipFile = new ZipFile(srcFile); 1333 zipInput = new FileInputStream(fileStr); 1334 zin = new ZipInputStream(zipInput); 1335 while ((entry = zin.getNextEntry()) != null) { 1336 if (entry.getName().toLowerCase().equals(MODULE_JSON)) { 1337 utility.setIsModuleJson(true); 1338 inputStream = zipFile.getInputStream(entry); 1339 reader = new InputStreamReader(inputStream); 1340 br = new BufferedReader(reader); 1341 if (br != null) { 1342 moduleJson = br.readLine(); 1343 break; 1344 } 1345 } 1346 } 1347 } catch (IOException exception) { 1348 LOG.error("Compressor::checkModuleTypeInHaps io exception: " + exception.getMessage()); 1349 throw new BundleException("Compressor::checkModuleTypeInHaps failed"); 1350 } finally { 1351 Utility.closeStream(zipFile); 1352 Utility.closeStream(zipInput); 1353 Utility.closeStream(zin); 1354 Utility.closeStream(inputStream); 1355 Utility.closeStream(reader); 1356 Utility.closeStream(br); 1357 } 1358 return moduleJson; 1359 } 1360 1361 /** 1362 * check version code in haps. 1363 * 1364 * @param utility common data 1365 * @param srcFile source file to zip 1366 * @param baseDir current directory name of file 1367 * @return true is for successful and false is for failed 1368 * @throws BundleException FileNotFoundException|IOException. 1369 */ checkVersionInHaps(Utility utility, File srcFile, String baseDir)1370 private boolean checkVersionInHaps(Utility utility, File srcFile, String baseDir) throws BundleException { 1371 try { 1372 String fileStr = srcFile.getName(); 1373 if ((fileStr == null) || (fileStr.isEmpty())) { 1374 throw new BundleException("Compressor::checkVersionInHaps get file name failed"); 1375 } 1376 if (!fileStr.toLowerCase(Locale.ENGLISH).endsWith(HAP_SUFFIX)) { 1377 return true; 1378 } 1379 for (String hapPath : utility.getFormattedHapPathList()) { 1380 if ((hapPath == null) || (hapPath.isEmpty()) || (!hapPath.contains(baseDir))) { 1381 continue; 1382 } 1383 String versionStr = obtainVersion(srcFile, hapPath); 1384 String code = obtainInnerVersionCode(versionStr); 1385 if ((code == null) || (code.isEmpty())) { 1386 LOG.error("Compressor::checkVersionInHaps version code is null or empty"); 1387 return false; 1388 } 1389 if (!versionCode.isEmpty() && !versionCode.equals(code)) { 1390 LOG.error("Compressor::checkVersionInHaps some haps with different version code"); 1391 return false; 1392 } 1393 String name = obtainInnerVersionName(versionStr); 1394 if ((name == null) || (name.isEmpty())) { 1395 LOG.error("Compressor::checkVersionInHaps version name is null or empty"); 1396 return false; 1397 } 1398 if (!versionName.isEmpty() && !versionName.equals(name)) { 1399 LOG.error("Compressor::checkVersionInHaps some haps with different version name"); 1400 return false; 1401 } 1402 versionCode = code; 1403 versionName = name; 1404 } 1405 } catch (BundleException exception) { 1406 LOG.error("Compressor::checkVersionInHaps io exception: " + exception.getMessage()); 1407 throw new BundleException("Compressor::checkVersionInHaps failed"); 1408 } 1409 return true; 1410 } 1411 1412 /** 1413 * get CRC32 from file. 1414 * 1415 * @param utility common data 1416 * @param file source file 1417 * @return CRC32 1418 * @throws BundleException FileNotFoundException|IOException. 1419 */ getCrcFromFile(Utility utility, File file)1420 private CRC32 getCrcFromFile(Utility utility, File file) throws BundleException { 1421 FileInputStream fileInputStream = null; 1422 CRC32 crc = new CRC32(); 1423 try { 1424 fileInputStream = new FileInputStream(file); 1425 byte[] buffer = new byte[BUFFER_SIZE]; 1426 1427 int count = fileInputStream.read(buffer); 1428 while (count > 0) { 1429 crc.update(buffer, 0, count); 1430 count = fileInputStream.read(buffer); 1431 } 1432 } catch (FileNotFoundException ignored) { 1433 LOG.error("Compressor::getCrcFromFile file not found exception"); 1434 throw new BundleException("Get Crc from file failed"); 1435 } catch (IOException exception) { 1436 LOG.error("Compressor::getCrcFromFile io exception: " + exception.getMessage()); 1437 throw new BundleException("Get Crc from file failed"); 1438 } finally { 1439 Utility.closeStream(fileInputStream); 1440 } 1441 return crc; 1442 } 1443 infoSpecialProcess(Utility utility, File srcFile)1444 private void infoSpecialProcess(Utility utility, File srcFile) 1445 throws BundleException { 1446 FileInputStream fileInputStream = null; 1447 BufferedReader bufferedReader = null; 1448 InputStreamReader inputStreamReader = null; 1449 1450 try { 1451 fileInputStream = new FileInputStream(srcFile); 1452 inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8); 1453 bufferedReader = new BufferedReader(inputStreamReader); 1454 bufferedReader.mark((int) srcFile.length() + 1); 1455 // parse moduleName from pack.info 1456 parsePackModuleName(bufferedReader, utility); 1457 bufferedReader.reset(); 1458 parsePackFormName(bufferedReader, utility); 1459 bufferedReader.reset(); 1460 parseDeviceType(bufferedReader, utility); 1461 bufferedReader.reset(); 1462 1463 Pattern pattern = Pattern.compile(System.lineSeparator()); 1464 String str = bufferedReader.readLine(); 1465 StringBuilder builder = new StringBuilder(); 1466 while (str != null) { 1467 Matcher matcher = pattern.matcher(str.trim()); 1468 String dest = matcher.replaceAll(""); 1469 builder.append(dest); 1470 str = bufferedReader.readLine(); 1471 } 1472 } catch (IOException exception) { 1473 LOG.error("Compressor::jsonSpecialProcess io exception: " + exception.getMessage()); 1474 throw new BundleException("Json special process failed"); 1475 } finally { 1476 Utility.closeStream(bufferedReader); 1477 Utility.closeStream(inputStreamReader); 1478 Utility.closeStream(fileInputStream); 1479 } 1480 } 1481 1482 /** 1483 * trim and remove "\r\n" in *.json file. 1484 * 1485 * @param utility common data 1486 * @param srcFile file input 1487 * @param entry zip file entry 1488 * @throws BundleException FileNotFoundException|IOException. 1489 */ jsonSpecialProcess(Utility utility, File srcFile, ZipEntry entry)1490 private void jsonSpecialProcess(Utility utility, File srcFile, ZipEntry entry) 1491 throws BundleException { 1492 FileInputStream fileInputStream = null; 1493 BufferedReader bufferedReader = null; 1494 InputStreamReader inputStreamReader = null; 1495 1496 try { 1497 fileInputStream = new FileInputStream(srcFile); 1498 inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8); 1499 bufferedReader = new BufferedReader(inputStreamReader); 1500 bufferedReader.mark((int) srcFile.length() + 1); 1501 // parse moduleName from config.json 1502 parseModuleName(bufferedReader, utility); 1503 bufferedReader.reset(); 1504 parseCompressNativeLibs(bufferedReader, utility); 1505 bufferedReader.reset(); 1506 parseDeviceType(bufferedReader, utility); 1507 bufferedReader.reset(); 1508 1509 Pattern pattern = Pattern.compile(System.lineSeparator()); 1510 String str = bufferedReader.readLine(); 1511 StringBuilder builder = new StringBuilder(); 1512 while (str != null) { 1513 Matcher matcher = pattern.matcher(str.trim()); 1514 String dest = matcher.replaceAll(""); 1515 builder.append(dest); 1516 str = bufferedReader.readLine(); 1517 } 1518 byte[] trimJson = builder.toString().getBytes(StandardCharsets.UTF_8); 1519 1520 // update crc 1521 CRC32 crc = new CRC32(); 1522 crc.update(trimJson); 1523 entry.setCrc(crc.getValue()); 1524 1525 // update size 1526 entry.setSize(trimJson.length); 1527 entry.setCompressedSize(trimJson.length); 1528 1529 // update fileTime 1530 FileTime fileTime = FileTime.fromMillis(FILE_TIME); 1531 entry.setLastAccessTime(fileTime); 1532 entry.setLastModifiedTime(fileTime); 1533 1534 // compress data 1535 zipOut.putNextEntry(entry); 1536 zipOut.write(trimJson); 1537 } catch (IOException exception) { 1538 LOG.error("Compressor::jsonSpecialProcess io exception: " + exception.getMessage()); 1539 throw new BundleException("Json special process failed"); 1540 } finally { 1541 Utility.closeStream(bufferedReader); 1542 Utility.closeStream(inputStreamReader); 1543 Utility.closeStream(fileInputStream); 1544 } 1545 } 1546 1547 /** 1548 * get string of config.json from hap file. 1549 * 1550 * @param file source file 1551 * @param baseDir current directory name of file 1552 * @return string of config.json 1553 * @throws BundleException FileNotFoundException|IOException. 1554 */ obtainVersion(File srcFile, String baseDir)1555 private String obtainVersion(File srcFile, String baseDir) throws BundleException { 1556 ZipFile zipFile = null; 1557 FileInputStream zipInput = null; 1558 InputStream in = null; 1559 ZipInputStream zin = null; 1560 InputStream inputStream = null; 1561 InputStreamReader reader = null; 1562 BufferedReader br = null; 1563 ZipEntry entry = null; 1564 String configJson = ""; 1565 try { 1566 zipFile = new ZipFile(srcFile); 1567 zipInput = new FileInputStream(baseDir); 1568 in = new BufferedInputStream(zipInput); 1569 zin = new ZipInputStream(in); 1570 while ((entry = zin.getNextEntry()) != null) { 1571 if (entry.getName().toLowerCase().equals(CONFIG_JSON)) { 1572 inputStream = zipFile.getInputStream(entry); 1573 reader = new InputStreamReader(inputStream); 1574 br = new BufferedReader(reader); 1575 if (br != null) { 1576 configJson = br.readLine(); 1577 break; 1578 } 1579 } 1580 } 1581 } catch (IOException exception) { 1582 LOG.error("Compressor::ObtainVersionCode io exception: " + exception.getMessage()); 1583 throw new BundleException("Compressor::ObtainVersionCode failed"); 1584 } finally { 1585 Utility.closeStream(zipFile); 1586 Utility.closeStream(zipInput); 1587 Utility.closeStream(in); 1588 Utility.closeStream(zin); 1589 Utility.closeStream(inputStream); 1590 Utility.closeStream(reader); 1591 Utility.closeStream(br); 1592 } 1593 return obtainInnerVersion(configJson); 1594 } 1595 obtainInnerVersion(String configJson)1596 private String obtainInnerVersion(String configJson) throws BundleException { 1597 try { 1598 if (configJson != null) { 1599 int indexOfVersion = configJson.indexOf(VERSION); 1600 if (indexOfVersion <= 0) { 1601 LOG.error("Compressor::obtainInnerVersion obtain index of version failed"); 1602 throw new BundleException("Compressor::obtainInnerVersion obtain index of version failed"); 1603 } 1604 int lastIndex = configJson.indexOf(JSON_END, indexOfVersion); 1605 if (lastIndex <= 0) { 1606 LOG.error("Compressor::obtainInnerVersion obtain last index failed"); 1607 throw new BundleException("Compressor::obtainInnerVersion obtain last index failed"); 1608 } 1609 String version = configJson.substring(indexOfVersion, lastIndex + 1); 1610 if (version == null || version.isEmpty()) { 1611 LOG.error("Compressor::obtainInnerVersion version is null or empty"); 1612 throw new BundleException("Compressor::obtainInnerVersion failed due to null or empty version!"); 1613 } 1614 return version.trim(); 1615 } 1616 } catch (BundleException exception) { 1617 LOG.error("Compressor::obtainInnerVersion io exception: " + exception.getMessage()); 1618 throw new BundleException("Compressor::obtainInnerVersion failed"); 1619 } 1620 return ""; 1621 } 1622 1623 /** 1624 * get version code from hap file. 1625 * 1626 * @param configJson config.json from hap file 1627 * @return version code 1628 * @throws BundleException FileNotFoundException|IOException. 1629 */ obtainInnerVersionCode(String configJson)1630 private String obtainInnerVersionCode(String configJson) throws BundleException { 1631 try { 1632 if (configJson != null) { 1633 int indexOfCode = configJson.indexOf(CODE); 1634 if (indexOfCode <= 0) { 1635 LOG.error("Compressor::ObtainInnerVersionCode obtain index failed"); 1636 throw new BundleException("Compressor::ObtainInnerVersionCode obtain index failed"); 1637 } 1638 int index = configJson.indexOf(COLON, indexOfCode); 1639 if (index <= 0) { 1640 LOG.error("Compressor::ObtainInnerVersionCode obtain index failed"); 1641 throw new BundleException("Compressor::ObtainInnerVersionCode obtain index failed"); 1642 } 1643 int lastIndex = configJson.indexOf(COMMA, index); 1644 if (lastIndex <= 0) { 1645 LOG.error("Compressor::ObtainInnerVersionCode obtain index failed"); 1646 throw new BundleException("Compressor::ObtainInnerVersionCode obtain index failed"); 1647 } 1648 String code = configJson.substring(index + 1, lastIndex); 1649 if (code == null || code.isEmpty()) { 1650 LOG.error("Compressor::ObtainInnerVersionCode code is null or empty"); 1651 throw new BundleException("Compressor::ObtainInnerVersionCode failed due to null or empty code!"); 1652 } 1653 return code.trim(); 1654 } 1655 } catch (BundleException exception) { 1656 LOG.error("Compressor::ObtainInnerVersionCode io exception: " + exception.getMessage()); 1657 throw new BundleException("Compressor::ObtainInnerVersionCode failed"); 1658 } 1659 return ""; 1660 } 1661 1662 /** 1663 * get version name from hap file. 1664 * 1665 * @param configJson config.json from hap file 1666 * @return version name 1667 * @throws BundleException FileNotFoundException|IOException. 1668 */ obtainInnerVersionName(String configJson)1669 private String obtainInnerVersionName(String configJson) throws BundleException { 1670 try { 1671 if (configJson != null) { 1672 int indexOfCode = configJson.indexOf(NAME); 1673 if (indexOfCode <= 0) { 1674 LOG.error("Compressor::obtainInnerVersionName obtain index failed"); 1675 throw new BundleException("Compressor::obtainInnerVersionName obtain index failed"); 1676 } 1677 int index = configJson.indexOf(COLON, indexOfCode); 1678 if (index <= 0) { 1679 LOG.error("Compressor::obtainInnerVersionName obtain index failed"); 1680 throw new BundleException("Compressor::obtainInnerVersionName obtain index failed"); 1681 } 1682 int lastIndex = configJson.indexOf(JSON_END, index); 1683 if (lastIndex <= 0) { 1684 LOG.error("Compressor::obtainInnerVersionName obtain index failed"); 1685 throw new BundleException("Compressor::obtainInnerVersionName obtain index failed"); 1686 } 1687 String name = configJson.substring(index + 1, lastIndex); 1688 if (name == null || name.isEmpty()) { 1689 LOG.error("Compressor::obtainInnerVersionName name is null or empty"); 1690 throw new BundleException("Compressor::obtainInnerVersionName failed due to null or empty name!"); 1691 } 1692 return name.trim(); 1693 } 1694 } catch (BundleException exception) { 1695 LOG.error("Compressor::obtainInnerVersionName io exception: " + exception.getMessage()); 1696 throw new BundleException("Compressor::obtainInnerVersionName failed"); 1697 } 1698 return ""; 1699 } 1700 1701 /** 1702 * Parse module name from config.json 1703 * 1704 * @param bufferedReader config.json buffered Reader 1705 * @param utility common data 1706 * @throws BundleException IOException 1707 */ parseModuleName(BufferedReader bufferedReader, Utility utility)1708 private void parseModuleName(BufferedReader bufferedReader, Utility utility) throws BundleException { 1709 String lineStr = null; 1710 boolean isDistroStart = false; 1711 try { 1712 while ((lineStr = bufferedReader.readLine()) != null) { 1713 if (!isDistroStart) { 1714 if (lineStr.contains(DISTRO)) { 1715 isDistroStart = true; 1716 } 1717 continue; 1718 } 1719 if (lineStr.contains(JSON_END)) { 1720 continue; 1721 } 1722 if (lineStr.contains(MODULE_NAME_NEW) || lineStr.contains(MODULE_NAME)) { 1723 getModuleNameFromString(lineStr, utility); 1724 break; 1725 } 1726 } 1727 } catch (IOException exception) { 1728 LOG.error("Compressor::parseModuleName io exception: " + exception.getMessage()); 1729 throw new BundleException("Parse module name failed"); 1730 } 1731 } 1732 1733 /** 1734 * Parse module name from pack.info 1735 * 1736 * @param bufferedReader pack.info buffered Reader 1737 * @param utility common data 1738 * @throws BundleException IOException 1739 */ parsePackModuleName(BufferedReader bufferedReader, Utility utility)1740 private void parsePackModuleName(BufferedReader bufferedReader, Utility utility) throws BundleException { 1741 String lineStr = null; 1742 boolean isDistroStart = false; 1743 try { 1744 while ((lineStr = bufferedReader.readLine()) != null) { 1745 if (lineStr.contains(DISTRO)) { 1746 continue; 1747 } 1748 if (lineStr.contains(JSON_END)) { 1749 continue; 1750 } 1751 if (lineStr.contains(MODULE_NAME_NEW) || lineStr.contains(MODULE_NAME)) { 1752 getModuleNameFromString(lineStr, utility); 1753 } 1754 } 1755 } catch (IOException exception) { 1756 LOG.error("Compressor::parseModuleName io exception: " + exception.getMessage()); 1757 throw new BundleException("Parse module name failed"); 1758 } 1759 } 1760 1761 /** 1762 * Parse Forms name from pack.info 1763 * 1764 * @param bufferedReader pack.info buffered Reader 1765 * @param utility common data 1766 * @throws BundleException IOException 1767 */ parsePackFormName(BufferedReader bufferedReader, Utility utility)1768 private void parsePackFormName(BufferedReader bufferedReader, Utility utility) throws BundleException { 1769 String lineStr = null; 1770 try { 1771 while ((lineStr = bufferedReader.readLine()) != null) { 1772 if (lineStr.contains("abilities")) { 1773 continue; 1774 } 1775 if (lineStr.contains(FORMS)) { 1776 continue; 1777 } 1778 if (lineStr.contains(JSON_END)) { 1779 continue; 1780 } 1781 if (lineStr.contains(NAME)) { 1782 getNameFromString(lineStr, utility); 1783 } 1784 } 1785 } catch (IOException exception) { 1786 LOG.error("Compressor::parseModuleName io exception: " + exception.getMessage()); 1787 throw new BundleException("Parse module name failed"); 1788 } 1789 } 1790 1791 1792 /** 1793 * Get name from line string 1794 * 1795 * @param lineStr line string 1796 * @param utility common data 1797 * @throws BundleException StringIndexOutOfBoundsException 1798 */ getNameFromString(String lineStr, Utility utility)1799 private void getNameFromString(String lineStr, Utility utility) throws BundleException { 1800 try { 1801 int endIndex = lineStr.lastIndexOf(SEMICOLON); 1802 if (endIndex <= 0) { 1803 LOG.error("Compressor::getModuleNameFromString field the json is not standard."); 1804 throw new BundleException("Parse module name failed, module-name is invalid"); 1805 } 1806 int startIndex = lineStr.lastIndexOf(SEMICOLON, endIndex - 1) + 1; 1807 String formName = lineStr.substring(startIndex, endIndex); 1808 if (formName == null || formName.isEmpty()) { 1809 LOG.error("Compressor::getModuleNameFromString field module-name is empty"); 1810 throw new BundleException("Parse module name failed, module-name is empty"); 1811 } 1812 String[] nameList = formName.split("\\."); 1813 if (nameList.length <= 1) { 1814 formNamesList.add(formName); 1815 utility.addFormNameList(formName); 1816 } 1817 } catch (StringIndexOutOfBoundsException exception) { 1818 LOG.error("Compressor::parseModuleName field module-name is fault: " + exception.getMessage()); 1819 throw new BundleException("Parse module name failed, module-name is invalid"); 1820 } 1821 } 1822 1823 /** 1824 * Get module name from line string 1825 * 1826 * @param lineStr line string 1827 * @param utility common data 1828 * @throws BundleException StringIndexOutOfBoundsException 1829 */ getModuleNameFromString(String lineStr, Utility utility)1830 private void getModuleNameFromString(String lineStr, Utility utility) throws BundleException { 1831 try { 1832 int endIndex = lineStr.lastIndexOf(SEMICOLON); 1833 if (endIndex <= 0) { 1834 LOG.error("Compressor::getModuleNameFromString field the json is not standard."); 1835 throw new BundleException("Parse module name failed, module-name is invalid"); 1836 } 1837 int startIndex = lineStr.lastIndexOf(SEMICOLON, endIndex - 1) + 1; 1838 String moduleName = lineStr.substring(startIndex, endIndex); 1839 list.add(moduleName); 1840 if (moduleName == null || moduleName.isEmpty()) { 1841 LOG.error("Compressor::getModuleNameFromString field module-name is empty"); 1842 throw new BundleException("Parse module name failed, module-name is empty"); 1843 } 1844 utility.setModuleName(moduleName); 1845 } catch (StringIndexOutOfBoundsException exception) { 1846 LOG.error("Compressor::parseModuleName field module-name is fault: " + exception.getMessage()); 1847 throw new BundleException("Parse module name failed, module-name is invalid"); 1848 } 1849 } 1850 parseCompressNativeLibs(BufferedReader bufferedReader, Utility utility)1851 private void parseCompressNativeLibs(BufferedReader bufferedReader, Utility utility) throws BundleException { 1852 String lineStr = null; 1853 try { 1854 while ((lineStr = bufferedReader.readLine()) != null) { 1855 if (lineStr.contains(COMPRESS_NATIVE_LIBS)) { 1856 if (lineStr.contains(Utility.FALSE_STRING)) { 1857 utility.setIsCompressNativeLibs(false); 1858 break; 1859 } 1860 } 1861 } 1862 } catch (IOException exception) { 1863 LOG.error("Compressor::parseCompressNativeLibs io exception: " + exception.getMessage()); 1864 throw new BundleException("Parse compress native libs failed"); 1865 } 1866 } 1867 1868 /** 1869 * ZipOutputStream flush, closeEntry and finish. 1870 */ closeZipOutputStream()1871 private void closeZipOutputStream() { 1872 try { 1873 if (zipOut != null) { 1874 zipOut.flush(); 1875 } 1876 } catch (IOException exception) { 1877 LOG.error("Compressor::closeZipOutputStream flush exception " + exception.getMessage()); 1878 } 1879 try { 1880 if (zipOut != null) { 1881 zipOut.closeEntry(); 1882 } 1883 } catch (IOException exception) { 1884 LOG.error("Compressor::closeZipOutputStream close entry io exception " + exception.getMessage()); 1885 } 1886 try { 1887 if (zipOut != null) { 1888 zipOut.finish(); 1889 } 1890 } catch (IOException exception) { 1891 LOG.error("Compressor::closeZipOutputStream finish exception " + exception.getMessage()); 1892 } 1893 } 1894 1895 /** 1896 * Parse device type from config.json 1897 * 1898 * @param bufferedReader config.json buffered Reader 1899 * @param utility common data 1900 * @throws BundleException IOException 1901 */ parseDeviceType(BufferedReader bufferedReader, Utility utility)1902 private void parseDeviceType(BufferedReader bufferedReader, Utility utility) throws BundleException { 1903 String lineStr = null; 1904 boolean isDeviceTypeStart = false; 1905 try { 1906 while ((lineStr = bufferedReader.readLine()) != null) { 1907 if (!isDeviceTypeStart) { 1908 if (lineStr.contains(DEVICE_TYPE)) { 1909 isDeviceTypeStart = true; 1910 } 1911 continue; 1912 } 1913 if (lineStr.contains(JSON_END)) { 1914 break; 1915 } 1916 utility.setDeviceType(lineStr); 1917 break; 1918 } 1919 } catch (IOException exception) { 1920 LOG.error("Compressor::parseDeviceType io exception: " + exception.getMessage()); 1921 throw new BundleException("Parse device type failed"); 1922 } 1923 } 1924 } 1925