/* * Copyright (c) 2023 Huawei Device Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ohos; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; /** * scan info * * @since 2023/11/23 */ public class Scan { private static final String LINUX_FILE_SEPARATOR = "/"; private static final String EMPTY_STRING = ""; private static final String HTML_START = ""; private static final String HTML_END = ""; private static final String STAT_JSON = "stat.json"; private static final String STAT_HTML = "stat.html"; private static final String STAT_CSS = "stat.css"; private static final String HTML_HEAD = "" + "stat"; private static final String UNPACK_NAME = "unpack"; private static final String BACKUPS = "backups"; private static final String HAP = ".hap"; private static final String HSP = ".hsp"; private static final String TEMPLATE_HTML = "ohos/scan_template.html"; private static final String TEMPLATE_CSS = "ohos/scan_template.css"; private static final String DIV_BOX = "
"; private static final String HTML_BODY = ""; private static final String HTML_DIV_END = "
"; private static final String HTML_BODY_END = ""; private static final String USER_DIR = "user.dir"; private static final String HTML_BR = "
"; private static final int BUFFER_SIZE = 10 * 1024; private static final Log LOG = new Log(Scan.class.toString()); /** * start scan. * * @param utility common data * @return scanProcess if scan succeed */ public boolean scanProcess(Utility utility) { File destFile = new File(utility.getOutPath()); File outParentFile = destFile.getParentFile(); if ((outParentFile != null) && (!outParentFile.exists())) { if (!outParentFile.mkdirs()) { LOG.error(ScanErrorEnum.SCAN_MKDIRS_ERROR.toString()); return false; } } boolean scanResult = true; try { scanExecute(utility); } catch (FileNotFoundException exception) { scanResult = false; LOG.error(ScanErrorEnum.SCAN_NOT_FOUND_ERROR + exception.getMessage()); } catch (BundleException | NoSuchAlgorithmException | IOException exception) { scanResult = false; LOG.error(ScanErrorEnum.SCAN_REMIND_ERROR + exception.getMessage()); } finally { if (!scanResult) { LOG.error(ScanErrorEnum.SCAN_COMPRESS_ERROR.toString()); if (!destFile.delete()) { LOG.error(ScanErrorEnum.SCAN_DELETE_ERROR.toString()); } } } return scanResult; } private void scanExecute(Utility utility) throws BundleException, IOException, NoSuchAlgorithmException { List jsonList = new ArrayList<>(); String templateHtml = getJsTemplate(TEMPLATE_HTML); templateHtml = templateHtml.replace(HTML_BR, System.lineSeparator()); String htmlStr = HTML_START + HTML_HEAD + DIV_BOX + HTML_BODY + templateHtml; String currentDir = System.getProperty(USER_DIR); String targetPath = currentDir + LINUX_FILE_SEPARATOR + UNPACK_NAME; List fileList = getAllInputFileList(utility, targetPath); if (utility.getStatDuplicate()) { ScanStatDuplicate scanStatDuplicate = new ScanStatDuplicate(); String duplicateHtml = scanStatDuplicate.statDuplicate(utility, jsonList, fileList); htmlStr = htmlStr + duplicateHtml; } if (null != utility.getStatFileSize() && !utility.getStatFileSize().isEmpty()) { ScanStatFileSize scanStatFileSize = new ScanStatFileSize(); String fileSizeHtml = scanStatFileSize.statFileSize(utility, jsonList, fileList); htmlStr = htmlStr + fileSizeHtml; } if (utility.getStatSuffix()) { ScanStatSuffix scanStatSuffix = new ScanStatSuffix(); String suffixHtml = scanStatSuffix.statSuffix(utility, jsonList, fileList); htmlStr = htmlStr + suffixHtml; } if (!((!utility.getStatDuplicate()) && !utility.getStatSuffix() && EMPTY_STRING.equals(utility.getStatFileSize()))) { htmlStr = htmlStr + HTML_DIV_END + HTML_BODY_END + HTML_END; String jsonPath = utility.getOutPath() + LINUX_FILE_SEPARATOR + STAT_JSON; String htmlPath = utility.getOutPath() + LINUX_FILE_SEPARATOR + STAT_HTML; String cssPath = utility.getOutPath() + LINUX_FILE_SEPARATOR + STAT_CSS; writeFile(jsonPath, jsonList.toString()); writeFile(htmlPath, htmlStr); String templateCss = getJsTemplate(TEMPLATE_CSS); writeFile(cssPath, templateCss); } File deleteFile = new File(targetPath); deleteFile(deleteFile); } private List getAllInputFileList(Utility utility, String path) throws BundleException, IOException { ArrayList fileList = new ArrayList<>(); unpackHap(utility.getInput(), path); File file = new File(path); File[] files = file.listFiles(); if (files == null) { LOG.error(ScanErrorEnum.SCAN_NO_FILE_ERROR.toString()); return fileList; } String copyPath = path + LINUX_FILE_SEPARATOR + BACKUPS; for (File f : files) { String fileName = f.getName(); if (fileName.endsWith(HSP) || fileName.endsWith(HAP)) { String absolutePath = f.getCanonicalPath(); File destDir = new File(copyPath); if (!destDir.exists()) { destDir.mkdirs(); } String targetPath = copyPath + LINUX_FILE_SEPARATOR + fileName; File targetFile = new File(targetPath); File sourceFile = new File(absolutePath); FileUtils.copyFile(sourceFile, targetFile); File deleteFile = new File(absolutePath); deleteFile(deleteFile); String outPath = path + LINUX_FILE_SEPARATOR + fileName; File outDir = new File(outPath); if (!outDir.exists()) { outDir.mkdirs(); } unpackHap(targetPath, outPath); } } File deleteFile = new File(copyPath); deleteFile(deleteFile); FileUtils.getFileList(path, fileList); return fileList; } private static void unpackHap(String srcPath, String outPath) throws BundleException { try (FileInputStream fis = new FileInputStream(srcPath); ZipInputStream zipInputStream = new ZipInputStream(new BufferedInputStream(fis))) { File destDir = new File(outPath); if (!destDir.exists()) { destDir.mkdirs(); } unpackEntryToFile(zipInputStream, outPath); } catch (IOException e) { LOG.error(ScanErrorEnum.SCAN_UNPACK_ERROR + e.getMessage()); throw new BundleException(ScanErrorEnum.SCAN_UNPACK_ERROR.msg + e.getMessage()); } } private static void unpackEntryToFile(ZipInputStream zipInputStream, String outPath) throws BundleException, IOException { ZipEntry entry; while ((entry = zipInputStream.getNextEntry()) != null) { String entryName = entry.getName(); File entryFile = new File(outPath, entryName); if (entry.isDirectory()) { entryFile.mkdirs(); zipInputStream.closeEntry(); continue; } File parent = entryFile.getParentFile(); if (!parent.exists()) { parent.mkdirs(); } try (FileOutputStream fos = new FileOutputStream(entryFile)) { byte[] buffer = new byte[BUFFER_SIZE]; int bytesRead; while ((bytesRead = zipInputStream.read(buffer)) != -1) { fos.write(buffer, 0, bytesRead); } } catch (IOException e) { LOG.error(ScanErrorEnum.SCAN_UNPACK_ERROR + e.getMessage()); throw new BundleException(ScanErrorEnum.SCAN_UNPACK_ERROR.msg + e.getMessage()); } zipInputStream.closeEntry(); } } private static void deleteFile(File file) { if (file == null || !file.exists()) { return; } if (file.isDirectory()) { File[] files = file.listFiles(); for (File fileTmp : files) { deleteFile(fileTmp); } } file.delete(); } private static String getJsTemplate(String fileName) throws IOException { ClassLoader classLoader = Scan.class.getClassLoader(); URL resource = classLoader.getResource(fileName); try (BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(resource.openStream(), StandardCharsets.UTF_8))) { StringBuilder template = new StringBuilder(); String line; while ((line = bufferedReader.readLine()) != null) { template.append(line); } return template.toString(); } catch (IOException e) { LOG.error(ScanErrorEnum.SCAN_GET_JS_TEMPLATE_ERROR + e.getMessage()); throw new IOException(ScanErrorEnum.SCAN_GET_JS_TEMPLATE_ERROR.msg + e.getMessage()); } } private static void writeFile(String targetPath, String data) throws IOException { try (FileWriter fileWriter = new FileWriter(targetPath)) { fileWriter.write(data); fileWriter.flush(); } catch (IOException e) { LOG.error(ScanErrorEnum.SCAN_WRITEFILE_ERROR + e.getMessage()); throw new IOException(ScanErrorEnum.SCAN_WRITEFILE_ERROR.msg + e.getMessage()); } } }