From fa3039fd02640f064300f81e145c6a6d9eaee309 Mon Sep 17 00:00:00 2001 From: hupeixi Date: Mon, 20 Nov 2023 17:02:52 +0800 Subject: [PATCH 01/20] =?UTF-8?q?=E5=8C=85=E6=89=AB=E6=8F=8F=E5=B7=A5?= =?UTF-8?q?=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hupeixi --- BUILD.gn | 9 + META-INF/check_tool/MANIFEST.MF | 4 + OAT.xml | 1 + adapter/ohos/CommandParser.java | 20 + adapter/ohos/Scan.java | 1112 +++++++++++++++++++++++++++++++ adapter/ohos/ScanEntrance.java | 60 ++ adapter/ohos/ScanVerify.java | 97 +++ adapter/ohos/ShowHelp.java | 32 + adapter/ohos/Utility.java | 35 + build.py | 12 + checkTool.sh | 113 ++++ packingtool.gni | 2 + 12 files changed, 1497 insertions(+) create mode 100644 META-INF/check_tool/MANIFEST.MF create mode 100644 adapter/ohos/Scan.java create mode 100644 adapter/ohos/ScanEntrance.java create mode 100644 adapter/ohos/ScanVerify.java create mode 100644 checkTool.sh diff --git a/BUILD.gn b/BUILD.gn index 8cca83a6..bc69cc23 100755 --- a/BUILD.gn +++ b/BUILD.gn @@ -20,12 +20,14 @@ packing_tool("packing_tool") { "//developtools/packing_tool/haptobin.sh", "//developtools/packing_tool/packingTool.sh", "//developtools/packing_tool/unpackingTool.sh", + "//developtools/packing_tool/checkTool.sh", ] outputs = [ "${target_out_dir}/jar/haptobin_tool.jar", "${target_out_dir}/jar/app_unpacking_tool.jar", "${target_out_dir}/jar/app_packing_tool.jar", "${target_out_dir}/jar", + "${target_out_dir}/jar/app_check_tool.jar", ] } @@ -50,6 +52,13 @@ ohos_prebuilt_etc("app_packing_tool") { install_enable = false } +ohos_prebuilt_etc("app_check_tool") { + list = get_target_outputs(":packing_tool") + source = list[3] + deps = [ ":packing_tool" ] + install_enable = false +} + ohos_prebuilt_etc("fastjson-1.2.83") { source = "jar/fastjson-1.2.83.jar" install_enable = false diff --git a/META-INF/check_tool/MANIFEST.MF b/META-INF/check_tool/MANIFEST.MF new file mode 100644 index 00000000..83a23b98 --- /dev/null +++ b/META-INF/check_tool/MANIFEST.MF @@ -0,0 +1,4 @@ +Manifest-Version: 1.0 +Class-Path: fastjson-1.2.83.jar +Created-By: javac.py +Main-Class: ohos.ScanEntrance diff --git a/OAT.xml b/OAT.xml index 33fe5d8c..85281534 100644 --- a/OAT.xml +++ b/OAT.xml @@ -61,6 +61,7 @@ Note:If the text contains special characters, please escape them according to th + diff --git a/adapter/ohos/CommandParser.java b/adapter/ohos/CommandParser.java index 4b0f7077..9160429a 100644 --- a/adapter/ohos/CommandParser.java +++ b/adapter/ohos/CommandParser.java @@ -86,6 +86,10 @@ public class CommandParser { private static final String VERSION_CODE = "--version-code"; private static final String VERSION_NAME = "--version-name"; private static final String INPUT_LIST = "--input-list"; + private static final String INPUT = "--input"; + private static final String STAT_DUPLICATE = "--stat-duplicate"; + private static final String STAT_SUFFIX = "--stat-suffix"; + private static final String STAT_FILE_SIZE = "--stat-file-size"; private static final int PARSE_MODE_VALUE_LENGTH = 2; private static final Log LOG = new Log(CommandParser.class.toString()); private static final Map, Boolean>> commandFuncs = new HashMap<>(); @@ -295,6 +299,22 @@ public class CommandParser { entry.getKey().setInputList(entry.getValue()); return true; }); + commandFuncs.put(INPUT, entry -> { + entry.getKey().setInput(entry.getValue()); + return true; + }); + commandFuncs.put(STAT_DUPLICATE, entry -> { + entry.getKey().setStatDuplicate(entry.getValue()); + return true; + }); + commandFuncs.put(STAT_SUFFIX, entry -> { + entry.getKey().setStatSuffix(entry.getValue()); + return true; + }); + commandFuncs.put(STAT_FILE_SIZE, entry -> { + entry.getKey().setStatFileSize(entry.getValue()); + return true; + }); } diff --git a/adapter/ohos/Scan.java b/adapter/ohos/Scan.java new file mode 100644 index 00000000..a93192fc --- /dev/null +++ b/adapter/ohos/Scan.java @@ -0,0 +1,1112 @@ +/* + * Copyright (c) 2021-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 com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; + +import java.io.BufferedInputStream; +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.InputStream; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Comparator; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + + +/** + * bundle compressor class, compress file and directory. + * + */ +public class Scan { + private static final String TRUE = "true"; + private static final String FALSE = "false"; + private static final String LINUX_FILE_SEPARATOR = "/"; + private static final String WIN_FILE_SEPARATOR = "\\"; + private static final String WIN = "Win"; + private static final String OS_NAME = "os.name"; + private static final String DUPLICATE_FOLDER_NAME = "duplicate"; + private static final String BACKUPS = "backups"; + private static final String SUFFIX_FOLDER_NAME = "suffix"; + private static final String FILE_SIZE_FOLDER_NAME = "fileSize"; + private static final String EMPTY_STRING = ""; + private static final String MD5 = "MD5"; + private static final String RESULT_MD5 = "md5"; + private static final String RESULT_SIZE = "size"; + private static final String RESULT_COMPRESS = "compress"; + private static final String RESULT_FILES = "files"; + private static final String RESULT_FILE = "file"; + private static final String RESULT_TOTAL_SIZE = "totalSize"; + private static final String DUPLICATE_DESC = "find the duplicated files"; + private static final String DUPLICATE_PARAM = "--stat-duplicate"; + private static final String SUFFIX_DESC = "show files group by file type[.suffix]"; + private static final String SUFFIX_PARAM = "--stat-suffix"; + private static final String SUFFIX_TYPE_UNKOWN = "umkonwnType"; + private static final String FILE_SIZE_DESC = "find files whose size exceed the limit size"; + private static final String FILE_SIZE_PARAM = "--stat-file-size"; + private static final String FILE_SIZE_PARAM_SEPARATOR = " "; + private static final String FILE_SIZE_PARAM_VALUE = "%s"; + private static final String FILE_SIZE_RESULT_SIZE = "size"; + private static final String FILE_SIZE_RESULT_FILE = "file"; + private static final String HTML_START = ""; + private static final String HTML_END = ""; + private static final String TASK_TYPE = "taskType"; + private static final String TASK_DESC = "taskDesc"; + private static final String PARAM = "param"; + private static final String START_TIME = "startTime"; + private static final String STOP_TIME = "stopTime"; + private static final String PATH_LIST = "pathList"; + private static final String RESULT = "result"; + private static final String STAT_JSON = "stat.json"; + private static final String STAT_HTML = "stat.html"; + private static final String HAP = ".hap"; + private static final String HSP = ".hsp"; + private static final String STAT_CSS = "stat.css"; + private static final String FILE_TYPE_SO = "so"; + private static final String TMP_FOLDER_NAME = "temporary"; + private static final String LIBS_NAME = "libs"; + private static final int BUFFER_SIZE = 10 * 1024; + private static final int MD5_BUFFER_SIZE = 1024; + private static final long ZERO = 0; + private static final int NUM_ZERO = 0; + private static final long DUPLICATE_TYPE = 1; + private static final long SUFFIX_TYPE = 3; + private static final long FILE_SIZE_TYPE = 2; + private static final long SCAN_LEVEL = 2; + private static final int MINUS_ONE = -1; + private static final int MD5_LENGTH = 16; + private static final long SHOW_SIZE = 10; + private static final String HTML_HEAD = "" + + "stat"; + private static final String HTML_BUTTON_SHOW = ""; + private static final String HTML_BUTTON_HIDE = ""; + private static final String HTML_FUNCTION = ""; + private static final String CSS_TEMPLATE = "#box {\n" + + " width: 1200px;\n" + + " margin: auto;\n" + + "}\n" + + ".boxTable {\n" + + " border: 1px solid black;\n" + + " width: 100%;\n" + + " height: 200px;\n" + + "}\n" + + ".layout {\n" + + " height: 30px;\n" + + "}\n" + + ".key {\n" + + " border: 1px solid black;\n" + + " width: 10%;\n" + + " }\n" + + ".value {\n" + + " border: 1px solid black;\n" + + " width: 90%;\n" + + "}\n" + + ".result {\n" + + " height: 30px;\n" + + "}\n" + + ".duplicateTable {\n" + + " border: 1px solid black;\n" + + " width: 100%;\n" + + " height: 100px;\n" + + "}\n" + + ".duplicateLayout {\n" + + " height: 30px;\n" + + "}\n" + + ".duplicateKey {\n" + + " border: 1px solid black;\n" + + " width: 60px;\n" + + "}\n" + + ".duplicateValue {\n" + + " border: 1px solid black;\n" + + " width: 840px;\n" + + "}\n" + + ".fileSizeTable {\n" + + " border: 1px solid black;\n" + + " width: 100%;\n" + + " height: 100px;\n" + + "}\n" + + ".fileSizeLayout {\n" + + " height: 30px;\n" + + "}\n" + + ".fileSizeKey {\n" + + " border: 1px solid black;\n" + + " width: 5%;\n" + + "}\n" + + ".fileSizeValue {\n" + + " border: 1px solid black;\n" + + " width: 95%;\n" + + "}\n" + + ".suffixTable {\n" + + " border: 1px solid black;\n" + + " width: 100%;\n" + + " height: 100px;\n" + + "}\n" + + ".suffixLayout {\n" + + " height: 30px;\n" + + "}\n" + + ".suffixKey {\n" + + " border: 1px solid black;\n" + + " width: 60px;\n" + + "}\n" + + ".suffixValue {\n" + + " border: 1px solid black;\n" + + " width: 840px;\n" + + "}\n" + + ".duplicate {\n" + + " display: none;\n" + + "}\n" + + ".suffix {\n" + + " display: none;\n" + + "}\n" + + ".fileSize {\n" + + " display: none;\n" + + " height: 30px;\n" + + "}\n" + + "button {\n" + + "}"; + private static final Log LOG = new Log(Scan.class.toString()); + + private static class ParamModel { + private String md5 = EMPTY_STRING; + private long size = ZERO; + + private List files = new ArrayList<>(); + + public String getMd5() { + return this.md5; + } + public void setMd5(String md5) { + this.md5 = md5; + } + public long getSize() { + return this.size; + } + public void setSize(long size) { + this.size = size; + } + public List getFiles() { + return this.files; + } + public void setFiles(List files) { + this.files = files; + } + } + + private static class ParamModelSuffixSon { + private String file = EMPTY_STRING; + private long size = ZERO; + + public String getFile() { + return this.file; + } + public void setFile(String file) { + this.file = file; + } + public long getSize() { + return this.size; + } + public void setSize(long size) { + this.size = size; + } + + } + private static class ParamModelSuffixSo extends ParamModelSuffixSon { + private String compress = FALSE; + public String getCompress() { + return this.compress; + } + public void setCompress(String compress) { + this.compress = compress; + } + } + + private static class ParamModelSuffix { + private String suffix = EMPTY_STRING; + private long totalSize = ZERO; + private List files = new ArrayList<>(); + public String getSuffix() { + return this.suffix; + } + public void setSuffix(String suffix) { + this.suffix = suffix; + } + public long getTotalSize() { + return this.totalSize; + } + public void setTotalSize(long totalSize) { + this.totalSize = totalSize; + } + public List getFiles() { + return this.files; + } + public void setFiles(List files) { + this.files = files; + } + } + + private static class DuplicateResult { + private long taskType = DUPLICATE_TYPE; + private String taskDesc = DUPLICATE_DESC; + private String param = DUPLICATE_PARAM; + private String startTime = EMPTY_STRING; + private String stopTime = EMPTY_STRING; + private List result = new ArrayList<>(); + public long getTaskType() { + return this.taskType; + } + public void setTaskType(long taskType) { + this.taskType = taskType; + } + public String getTaskDesc() { + return this.taskDesc; + } + public void setTaskDesc(String taskDesc) { + this.taskDesc = taskDesc; + } + public String getParam() { + return this.param; + } + public void setParam(String param) { + this.param = param; + } + public String getStartTime() { + return this.startTime; + } + public void setStartTime(String startTime) { + this.startTime = startTime; + } + public String getStopTime() { + return this.stopTime; + } + public void setStopTime(String stopTime) { + this.stopTime = stopTime; + } + public List getResult() { + return this.result; + } + public void setResult(List result) { + this.result = result; + } + } + + private static class SuffixResult { + private long taskType = SUFFIX_TYPE; + private String taskDesc = SUFFIX_DESC; + private String param = SUFFIX_PARAM; + private String startTime = EMPTY_STRING; + private String stopTime = EMPTY_STRING; + private List pathList = new ArrayList<>(); + private List result = new ArrayList<>(); + public long getTaskType() { + return this.taskType; + } + public void setTaskType(long taskType) { + this.taskType = taskType; + } + public String getTaskDesc() { + return this.taskDesc; + } + public void setTaskDesc(String taskDesc) { + this.taskDesc = taskDesc; + } + public String getParam() { + return this.param; + } + public void setParam(String param) { + this.param = param; + } + public String getStartTime() { + return this.startTime; + } + public void setStartTime(String startTime) { + this.startTime = startTime; + } + public String getStopTime() { + return this.stopTime; + } + public void setStopTime(String stopTime) { + this.stopTime = stopTime; + } + public List getResult() { + return this.result; + } + public void setResult(List result) { + this.result = result; + } + public List getPathList() { + return this.pathList; + } + public void setPathList(List pathList) { + this.pathList = pathList; + } + } + + private static class ParamModelFileSize { + private String file = EMPTY_STRING; + private long size = ZERO; + public long getSize() { + return this.size; + } + public void setSize(long size) { + this.size = size; + } + public String getFile() { + return file; + } + public void setFile(String file) { + this.file = file; + } + } + + private static class FileSizeResult { + private long taskType = FILE_SIZE_TYPE; + private String taskDesc = FILE_SIZE_DESC; + private String param = FILE_SIZE_PARAM + FILE_SIZE_PARAM_SEPARATOR + FILE_SIZE_PARAM_VALUE; + private String startTime = EMPTY_STRING; + private String stopTime = EMPTY_STRING; + private List result = new ArrayList<>(); + public long getTaskType() { + return this.taskType; + } + public void setTaskType(long taskType) { + this.taskType = taskType; + } + public String getTaskDesc() { + return this.taskDesc; + } + public void setTaskDesc(String taskDesc) { + this.taskDesc = taskDesc; + } + public String getParam() { + return this.param; + } + public void setParam(String param) { + this.param = param; + } + public String getStartTime() { + return this.startTime; + } + public void setStartTime(String startTime) { + this.startTime = startTime; + } + public String getStopTime() { + return this.stopTime; + } + public void setStopTime(String stopTime) { + this.stopTime = stopTime; + } + public List getResult() { + return this.result; + } + public void setResult(List result) { + this.result = result; + } + } + + /** + * start scan. + * file orders as follows: + * for hap: 1.config.json 2.lib 3.res 4.assets 5.*.so 6.*.dex 7.*.apk 8.resources.index + * for app: 1.certificate 2.signature 3.pack.info 4.hap (1 and 2 may not be used) + * + * @param utility common data + * @return scanProcess if scan succeed + */ + public boolean scanProcess(Utility utility) { + File destFile = new File(utility.getOutPath()); + + // if out file directory not exist, mkdirs. + File outParentFile = destFile.getParentFile(); + if ((outParentFile != null) && (!outParentFile.exists())) { + if (!outParentFile.mkdirs()) { + LOG.error("Scan::scanProcess create out file parent directory failed."); + return false; + } + } + boolean scanResult = true; + try { + scanExcute(utility); + } catch (FileNotFoundException exception) { + scanResult = false; + LOG.error("Scan::scanProcess file not found exception" + exception.getMessage()); + } catch (BundleException | IOException exception) { + scanResult = false; + LOG.error("Scan::scanProcess Bundle exception."); + } + // if scan failed, delete out file. + if (!scanResult) { + LOG.error("Scan::scanProcess compress failed."); + if (!destFile.delete()) { + LOG.error("Scan::scanProcess delete dest file failed."); + } + } + return scanResult; + } + + private void scanExcute(Utility utility) throws BundleException, IOException { + List jsonList = new ArrayList<>(); + String htmlStr = HTML_START + HTML_HEAD + "
" + "" + HTML_FUNCTION; + if (TRUE.equals(utility.getStatDuplicate())) { + String duplicateHtml = statDuplicate(utility, jsonList); + htmlStr = htmlStr + duplicateHtml; + } + if (null != utility.getStatFileSize() && !utility.getStatFileSize().isEmpty()) { + String fileSizeHtml = statFileSize(utility, jsonList); + htmlStr = htmlStr + fileSizeHtml; + } + if (TRUE.equals(utility.getStatSuffix())) { + String suffixHtml = statSuffix(utility, jsonList); + htmlStr = htmlStr + suffixHtml; + } + if (!((FALSE.equals(utility.getStatDuplicate())) && FALSE.equals(utility.getStatSuffix()) + && EMPTY_STRING.equals(utility.getStatFileSize()))) { + htmlStr = htmlStr + "
" + "" + 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); + writeFile(cssPath, CSS_TEMPLATE); + } + } + + 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("getAllInputFileList: no file in this file path."); + return fileList; + } + String copyPath = path + LINUX_FILE_SEPARATOR + BACKUPS; + for (File f : files) { + String fName = f.getName(); + if (fName.endsWith(HSP) || fName.endsWith(HAP)) { + // copy file and delete file + String absolutePath = f.getAbsolutePath(); + File destDir = new File(copyPath); + if (!destDir.exists()) { + destDir.mkdirs(); + } + String targetPath = copyPath + LINUX_FILE_SEPARATOR + fName; + File targetFile = new File(targetPath); + File sourceFile = new File(absolutePath); + FileUtils.copyFile(sourceFile, targetFile); + deleteFile(absolutePath); + String outPath = path + LINUX_FILE_SEPARATOR + fName; + File outDir = new File(outPath); + if (!outDir.exists()) { + outDir.mkdirs(); + } + unpackHap(targetPath, outPath); + } + } + + deleteFile(copyPath); + FileUtils.getFileList(path, fileList); + return fileList; + } + + private String statDuplicate(Utility utility, List jsonList) + throws BundleException, IOException { + DuplicateResult duplicateResult = new DuplicateResult(); + // set start time + duplicateResult.setStartTime(getCurrentTime()); + String currentDir = System.getProperty("user.dir"); + String targetPath = currentDir + LINUX_FILE_SEPARATOR + DUPLICATE_FOLDER_NAME; + + // scan all files + List fileList = getAllInputFileList(utility, targetPath); + List resList = new ArrayList<>(); + for (String filePath: fileList) { + boolean addFlag = true; + String md5 = md5HashCode(filePath); + for (ParamModel element: resList) { + String eleMd5 = element.getMd5(); + if (eleMd5.equals(md5)) { + List eleFiles = element.getFiles(); + eleFiles.add(cutPath(filePath, DUPLICATE_FOLDER_NAME)); + element.setFiles(eleFiles); + addFlag = false; + } + } + if (addFlag) { + ParamModel model = new ParamModel(); + long size = FileUtils.getFileSize(filePath); + model.setMd5(md5); + model.setSize(size); + List files = model.getFiles(); + files.add(cutPath(filePath, DUPLICATE_FOLDER_NAME)); + resList.add(model); + } + } + File parentFile = new File(utility.getOutPath()); + if (!parentFile.exists()) { + if (!parentFile.mkdirs()) { + LOG.error("Compressor::compressHapAddition create target file parent directory failed."); + } + } + duplicateResult.setResult(resList); + String jsonStr = JSON.toJSONString(duplicateResult, new SerializerFeature[]{ + SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue, + SerializerFeature.WriteDateUseDateFormat}); + // set stop time + duplicateResult.setStopTime(getCurrentTime()); + String taskTypeHtml = getHtmlRow(TASK_TYPE, duplicateResult.getTaskType()); + String taskDescHtml = getHtmlRow(TASK_DESC, duplicateResult.getTaskDesc()); + String paramHtml = getHtmlRow(PARAM, duplicateResult.getParam()); + String startTimeHtml = getHtmlRow(START_TIME, duplicateResult.getStartTime()); + String stopTimeHtml = getHtmlRow(STOP_TIME, duplicateResult.getStopTime()); + String resultValue = getResultHtml(duplicateResult.getResult()); + String resultHtml = getHtmlRowResultClass(RESULT, resultValue); + String htmlStr = "" + taskTypeHtml + taskDescHtml + paramHtml + + startTimeHtml + stopTimeHtml + resultHtml + "
"; + deleteFile(targetPath); + jsonList.add(jsonStr); + return htmlStr; + } + + private String statSuffix(Utility utility, List jsonList) + throws BundleException, IOException { + SuffixResult suffixResult = new SuffixResult(); + suffixResult.setStartTime(getCurrentTime()); + String currentDir = System.getProperty("user.dir"); + String targetPath = currentDir + LINUX_FILE_SEPARATOR + SUFFIX_FOLDER_NAME; + + // scan all files + List fileList = getAllInputFileList(utility, targetPath); + HashMap> hashMap = new HashMap<>(); + for (String filePath: fileList) { + hashMap = accountFileType(hashMap, filePath); + } + Iterator iterator = hashMap.keySet().iterator(); + List resulList = new ArrayList<>(); + String outPath = currentDir + LINUX_FILE_SEPARATOR + TMP_FOLDER_NAME; + String packageName = utility.getInput(); + unpackHap(packageName, outPath); + List pathList = new ArrayList<>(); + ArrayList soList = new ArrayList<>(); + FileUtils.getFileList(outPath, soList); + String osName = System.getProperty(OS_NAME); + File pack = new File(packageName); + for (String file: soList) { + if (file.contains(HAP) || file.contains(HSP)) { + file = cutPath(file, TMP_FOLDER_NAME); + pathList.add(pack.getName() + file); + } + } + suffixResult.setPathList(pathList); + while (iterator.hasNext()) { + String next = iterator.next(); + ParamModelSuffix paramModelSuffix = new ParamModelSuffix(); + paramModelSuffix.setSuffix(next); + if (next.equalsIgnoreCase(FILE_TYPE_SO)) { + List paramModelSuffixSos = new ArrayList<>(); + List paramModelSuffixSons = hashMap.get(next); + long sum = ZERO; + for (ParamModelSuffixSon param:paramModelSuffixSons) { + ParamModelSuffixSo paramModelSuffixSo = new ParamModelSuffixSo(); + paramModelSuffixSo.setSize(param.getSize()); + String soFilePath = param.getFile(); + soFilePath = cutPath(soFilePath, SUFFIX_FOLDER_NAME); + paramModelSuffixSo.setFile(soFilePath); + int i = NUM_ZERO; + i = judgeValue(osName, i, soFilePath); + String hapPath = soFilePath.substring(NUM_ZERO, i); + File hapFile = new File(hapPath); + long oldSize = hapFile.length(); + long newSize = ZERO; + oldSize = setOldValue(soList, hapFile, oldSize); + newSize = setNewValue(paramModelSuffixSons, hapFile, newSize); + paramModelSuffixSo.setCompress(oldSize < newSize ? TRUE : FALSE); + paramModelSuffixSos.add(paramModelSuffixSo); + sum += param.getSize(); + } + deleteFile(outPath); + paramModelSuffix.setTotalSize(sum); + paramModelSuffixSos.sort(Comparator.comparing(ParamModelSuffixSo::getSize).reversed()); + paramModelSuffix.setFiles(paramModelSuffixSos); + } else { + List paramModelSuffixSons = hashMap.get(next); + for (ParamModelSuffixSon son:paramModelSuffixSons) { + String sonFilePath = son.getFile(); + son.setFile(cutPath(sonFilePath, SUFFIX_FOLDER_NAME)); + } + paramModelSuffixSons.sort(Comparator.comparing(ParamModelSuffixSon::getSize).reversed()); + paramModelSuffix.setFiles(paramModelSuffixSons); + long sum = paramModelSuffixSons.stream().mapToLong(ParamModelSuffixSon::getSize).sum(); + paramModelSuffix.setTotalSize(sum); + } + resulList.add(paramModelSuffix); + } + resulList.sort(Comparator.comparing(ParamModelSuffix::getTotalSize).reversed()); + suffixResult.setResult(resulList); + File parentFile = new File(utility.getOutPath()); + if (!parentFile.exists()) { + if (!parentFile.mkdirs()) { + LOG.error("Compressor::compressHapAddition create target file parent directory failed."); + } + } + deleteFile(outPath); + suffixResult.setStopTime(getCurrentTime()); + String jsonStr = JSON.toJSONString(suffixResult, new SerializerFeature[] { + SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue, + SerializerFeature.WriteDateUseDateFormat}); + String taskTypeHtml = getHtmlRow(TASK_TYPE, suffixResult.getTaskType()); + String taskDescHtml = getHtmlRow(TASK_DESC, suffixResult.getTaskDesc()); + String paramHtml = getHtmlRow(PARAM, suffixResult.getParam()); + String startTimeHtml = getHtmlRow(START_TIME, suffixResult.getStartTime()); + String stopTimeHtml = getHtmlRow(STOP_TIME, suffixResult.getStopTime()); + String pathHtml = EMPTY_STRING; + if (suffixResult.getPathList() != null && !suffixResult.getPathList().isEmpty()) { + pathHtml = getPathListHtml(suffixResult.getPathList()); + } + String pathListHtml = EMPTY_STRING; + if (!pathHtml.isBlank()) { + pathListHtml = getHtmlRow(PATH_LIST, pathHtml); + } + String resultValue = getResultHtmlOfSuffix(suffixResult.getResult()); + String resultHtml = getHtmlRowResultClass(RESULT, resultValue); + String htmlStr = "" + taskTypeHtml + taskDescHtml + paramHtml + + startTimeHtml + stopTimeHtml + pathListHtml + resultHtml + "
"; + deleteFile(targetPath); + jsonList.add(jsonStr); + return htmlStr; + } + + private String statFileSize(Utility utility, List jsonList) + throws BundleException, IOException { + FileSizeResult fileSizeResult = new FileSizeResult(); + // set start time + fileSizeResult.setStartTime(getCurrentTime()); + String currentDir = System.getProperty("user.dir"); + String targetPath = currentDir + LINUX_FILE_SEPARATOR + FILE_SIZE_FOLDER_NAME; + + // scan all files + List fileList = getAllInputFileList(utility, targetPath); + List resList = new ArrayList<>(); + for (String filePath : fileList) { + long statFileSize = Long.parseLong(utility.getStatFileSize()); + long size = FileUtils.getFileSize(filePath); + if (size > statFileSize) { + ParamModelFileSize model = new ParamModelFileSize(); + model.setFile(cutPath(filePath, FILE_SIZE_FOLDER_NAME)); + model.setSize(size); + resList.add(model); + } + } + // order by size from large to small + resList.sort(Comparator.comparing(ParamModelFileSize::getSize).reversed()); + fileSizeResult.setResult(resList); + // set param input size + fileSizeResult.setParam(String.format(fileSizeResult.getParam(), utility.getStatFileSize())); + // set stop time + fileSizeResult.setStopTime(getCurrentTime()); + File parentFile = new File(utility.getOutPath()); + if (!parentFile.exists()) { + if (!parentFile.mkdirs()) { + LOG.error("Compressor::compressHapAddition create target file parent directory failed."); + } + } + // output json result + String jsonStr = JSON.toJSONString(fileSizeResult, new SerializerFeature[]{ + SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue, + SerializerFeature.WriteDateUseDateFormat}); + // output html result + String taskTypeHtml = getHtmlRow(TASK_TYPE, fileSizeResult.getTaskType()); + String taskDescHtml = getHtmlRow(TASK_DESC, fileSizeResult.getTaskDesc()); + String paramHtml = getHtmlRow(PARAM, fileSizeResult.getParam()); + String startTimeHtml = getHtmlRow(START_TIME, fileSizeResult.getStartTime()); + String stopTimeHtml = getHtmlRow(STOP_TIME, fileSizeResult.getStopTime()); + String resultValue = getResultHtmlFileSize(fileSizeResult.getResult()); + String resultHtml = getHtmlRowResultClass(RESULT, resultValue); + String htmlStr = "" + taskTypeHtml + taskDescHtml + paramHtml + + startTimeHtml + stopTimeHtml + resultHtml + "
"; + deleteFile(targetPath); + jsonList.add(jsonStr); + return htmlStr; + } + private String cutPath(String path, String packageName) { + String[] split = path.split(packageName); + return split[1]; + } + private int judgeValue(String osName, int i, String soFilePath) { + if (osName.startsWith(WIN)) { + i = soFilePath.indexOf(WIN_FILE_SEPARATOR + LIBS_NAME); + } else { + i = soFilePath.indexOf(LINUX_FILE_SEPARATOR + LIBS_NAME); + } + return i; + } + private long setOldValue(List soList, File hapFile, long oldSize) { + for (String file: soList) { + File tmp = new File(file); + if (tmp.getName().equals(hapFile.getName())) { + oldSize = tmp.length(); + } + } + return oldSize; + } + private long setNewValue(List paramModelSuffixSons, File hapFile, long newSize) { + for (ParamModelSuffixSon so:paramModelSuffixSons) { + if (so.getFile().contains(hapFile.getPath())) { + File tmp = new File(so.getFile()); + newSize += tmp.length(); + } + } + return newSize; + } + + private static HashMap> accountFileType(HashMap> hashMap, String f) { + File file = new File(f); + String[] split = file.getName().split("\\."); + if (split.length == SCAN_LEVEL) { + if (hashMap.containsKey(split[1])) { + putValueIntoHashmap(hashMap, file, split[1]); + } else { + putValueIntoHashmapnew(hashMap, file, split[1]); + } + } else if (split.length == 1) { // no suffix + if (hashMap.containsKey(SUFFIX_TYPE_UNKOWN)) { + putValueIntoHashmap(hashMap, file, SUFFIX_TYPE_UNKOWN); + } else { + putValueIntoHashmapnew(hashMap, file, SUFFIX_TYPE_UNKOWN); + } + } + return hashMap; + } + + private static void putValueIntoHashmap(HashMap> hashMap, File file, String key) { + ParamModelSuffixSon paramModel2 = setModelValue(file); + List paramModel2s = hashMap.get(key); + paramModel2s.add(paramModel2); + hashMap.put(key, paramModel2s); + } + + private static void putValueIntoHashmapnew(HashMap> hashMap, + File file, String key) { + ParamModelSuffixSon paramModel2 = setModelValue(file); + List fileNew = new ArrayList<>(); + fileNew.add(paramModel2); + hashMap.put(key, fileNew); + } + + private static ParamModelSuffixSon setModelValue(File file) { + ParamModelSuffixSon paramModel2 = new ParamModelSuffixSon(); + paramModel2.setFile(file.getPath()); + long size = FileUtils.getFileSize(file.getPath()); + paramModel2.setSize(size); + return paramModel2; + } + + private static String getResultHtml(List models) { + StringBuilder resultHtml = new StringBuilder(EMPTY_STRING); + resultHtml.append("
    "); + for (int i = 0; i < models.size(); i++) { + ParamModel model = models.get(i); + String md5Html = getHtmlRowResult(RESULT_MD5, model.getMd5(), + " class=\"duplicateLayout\"", " class=\"duplicateKey\"", " class=\"duplicateValue\""); + String sizeHtml = getHtmlRowResult(RESULT_SIZE, model.getSize(), + " class=\"duplicateLayout\"", " class=\"duplicateKey\"", " class=\"duplicateValue\""); + String filesHtml = getHtmlRowResult(RESULT_FILES, model.getFiles()); + String liHtml; + if (SHOW_SIZE > i) { + liHtml = "
  • "; + } else { + liHtml = "
  • "; + } + String modelHtml = liHtml + "" + + md5Html + sizeHtml + filesHtml + "
  • "; + resultHtml.append(modelHtml); + } + resultHtml.append("
"); + if (models.size() > SHOW_SIZE) { + resultHtml.append(String.format(HTML_BUTTON_SHOW, DUPLICATE_FOLDER_NAME, DUPLICATE_FOLDER_NAME)); + resultHtml.append(String.format(HTML_BUTTON_HIDE, DUPLICATE_FOLDER_NAME, DUPLICATE_FOLDER_NAME)); + } + return resultHtml.toString(); + } + private static String getPathListHtml(List models) { + StringBuilder pathListHtml = new StringBuilder(EMPTY_STRING); + for (String strHtml : models) { + pathListHtml.append(strHtml).append("
"); + } + return pathListHtml.toString(); + } + + private static String getResultHtmlOfSuffix(List models) { + StringBuilder resultHtml = new StringBuilder(EMPTY_STRING); + resultHtml.append("
    "); + for (int i = 0; i < models.size(); i++) { + ParamModelSuffix model = models.get(i); + String suffixHtml = getHtmlRowResult(SUFFIX_FOLDER_NAME, model.getSuffix(), + " class=\"suffixLayout\"", " class=\"suffixKey\"", " class=\"suffixValue\""); + String totalSizeHtml = getHtmlRowResult(RESULT_TOTAL_SIZE, model.getTotalSize(), + " class=\"suffixLayout\"", " class=\"suffixKey\"", " class=\"suffixValue\""); + String filesHtml; + if (model.getSuffix().equalsIgnoreCase(FILE_TYPE_SO)) { + filesHtml = getHtmlRowSonSo(RESULT_FILES, model.getFiles()); + } else { + filesHtml = getHtmlRowSon(RESULT_FILES, model.getFiles()); + } + String liHtml; + if (SHOW_SIZE > i) { + liHtml = "
  • "; + } else { + liHtml = "
  • "; + } + String modelHtml = liHtml + "" + + suffixHtml + totalSizeHtml + filesHtml + "
  • "; + resultHtml.append(modelHtml); + } + resultHtml.append("
"); + if (models.size() > SHOW_SIZE) { + resultHtml.append(String.format(HTML_BUTTON_SHOW, SUFFIX_FOLDER_NAME, SUFFIX_FOLDER_NAME)); + resultHtml.append(String.format(HTML_BUTTON_HIDE, SUFFIX_FOLDER_NAME, SUFFIX_FOLDER_NAME)); + } + return resultHtml.toString(); + } + + private static String getResultHtmlFileSize(List models) { + StringBuilder resultHtml = new StringBuilder(EMPTY_STRING); + resultHtml.append(""); + String resultFieldHtml = getHtmlRowResult(FILE_SIZE_RESULT_FILE, FILE_SIZE_RESULT_SIZE, + " class=\"fileSizeLayout\"", " class=\"fileSizeKey\"", " class=\"fileSizeValue\""); + resultHtml.append(resultFieldHtml); + for (int i = 0; i < models.size(); i++) { + ParamModelFileSize model = models.get(i); + String resultRowHtml; + if (SHOW_SIZE > i) { + resultRowHtml = getHtmlRowResult(model.getFile(), model.getSize(), + " class=\"fileSizeLayout\"", " class=\"fileSizeKey\"", " class=\"fileSizeValue\""); + } else { + resultRowHtml = getHtmlRowResult(model.getFile(), model.getSize(), + " class=\"fileSize\"", " class=\"fileSizeKey\"", " class=\"fileSizeValue\""); + } + resultHtml.append(resultRowHtml); + } + resultHtml.append("
"); + if (models.size() > SHOW_SIZE) { + resultHtml.append(String.format(HTML_BUTTON_SHOW, FILE_SIZE_FOLDER_NAME, FILE_SIZE_FOLDER_NAME)); + resultHtml.append(String.format(HTML_BUTTON_HIDE, FILE_SIZE_FOLDER_NAME, FILE_SIZE_FOLDER_NAME)); + } + return resultHtml.toString(); + } + + private static String getHtmlRow(String key, String valve) { + return "" + key + "" + valve + ""; + } + + private static String getHtmlRow(String key, long valve) { + return "" + key + "" + valve + ""; + } + + private static String getHtmlRowResultClass(String key, String valve) { + return "" + key + "" + valve + ""; + } + + private static String getHtmlRowResult(String key, String valve, + String trClass, String tdClassKey, String tdClassValue) { + return String.format("" + key + "" + valve + "", + trClass, tdClassKey, tdClassValue); + } + + private static String getHtmlRowResult(String key, long valve, + String trClass, String tdClassKey, String tdClassValue) { + return String.format("" + key + "" + valve + "", + trClass, tdClassKey, tdClassValue); + } + + private static String getHtmlRowResult(String key, List valve) { + StringBuilder resValve = new StringBuilder(EMPTY_STRING); + for (String ele: valve) { + resValve.insert(0, "
  • " + ele + "
  • "); + } + return "" + key + + "
      " + resValve + "
    "; + } + + private static String getHtmlRowSon(String key, List files) { + StringBuilder resValve = new StringBuilder(EMPTY_STRING); + for (ParamModelSuffixSon so:files) { + resValve.insert(0, RESULT_FILE + ":" + so.getFile() + "
    "); + resValve.insert(0, RESULT_SIZE + ":" + so.getSize() + "
    "); + } + return "" + key + + "" + resValve + ""; + } + private static String getHtmlRowSonSo(String key, List files) { + StringBuilder resValve = new StringBuilder(EMPTY_STRING); + for (ParamModelSuffixSo so:files) { + resValve.insert(0, RESULT_FILE + ":" + so.getFile() + "
    "); + resValve.insert(0, RESULT_SIZE + ":" + so.getSize() + "
    "); + resValve.insert(0, RESULT_COMPRESS + ":" + so.getCompress() + "
    "); + } + return "" + key + + "" + resValve + ""; + } + + + private static String getCurrentTime() { + long currentTimeMillis = System.currentTimeMillis(); + return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS").format(currentTimeMillis); + } + + 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(); + } + + 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(); + } + + FileOutputStream fos = new FileOutputStream(entryFile); + byte[] buffer = new byte[BUFFER_SIZE]; + int bytesRead; + while ((bytesRead = zipInputStream.read(buffer)) != MINUS_ONE) { + fos.write(buffer, 0, bytesRead); + } + fos.close(); + zipInputStream.closeEntry(); + } + } catch (IOException e) { + LOG.error("unpack hap failed IOException " + e.getMessage()); + throw new BundleException("unpack hap failed IOException " + e.getMessage()); + } + } + + private String md5HashCode(String filePath) { + String md5 = ""; + try { + InputStream fis = new FileInputStream(filePath); + MessageDigest md = MessageDigest.getInstance(MD5); + byte[] buffer = new byte[MD5_BUFFER_SIZE]; + int length = MINUS_ONE; + while ((length = fis.read(buffer, 0, MD5_BUFFER_SIZE)) != MINUS_ONE) { + md.update(buffer, 0, length); + } + fis.close(); + byte[] md5Bytes = md.digest(); + BigInteger bigInt = new BigInteger(1, md5Bytes); + md5 = bigInt.toString(MD5_LENGTH); + } catch (Exception exception) { + LOG.error("Scan::md5HashCode exception" + exception); + } + return md5; + } + + /** + * delete file + * + * @param path file path which will be deleted + */ + private static void deleteFile(final String path) { + File file = new File(path); + if (file.exists()) { + if (file.isDirectory()) { + File[] files = file.listFiles(); + for (int i = 0; i < files.length; i++) { + deleteFile(files[i].toString()); + } + } + file.delete(); + } + } + + private static void writeFile(String targetPath, String data) throws IOException { + FileWriter fileWriter = new FileWriter(targetPath); + fileWriter.write(data); + fileWriter.flush(); + fileWriter.close(); + } + +} diff --git a/adapter/ohos/ScanEntrance.java b/adapter/ohos/ScanEntrance.java new file mode 100644 index 00000000..5d71b694 --- /dev/null +++ b/adapter/ohos/ScanEntrance.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 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; + +/** + * bundle scan. + * step1: parse arguments + * step2: verity arguments + * step3: uncompress arguments + * + */ +public class ScanEntrance { + private static final int EXIT_STATUS_NORMAL = 0; + private static final int EXIT_STATUS_EXCEPTION = 1; + private static final Log LOG = new Log(ScanEntrance.class.toString()); + + + /** + * scan tool main function. + * + * @param args command line + */ + public static void main(String[] args) { + Utility utility = new Utility(); + + if (!CommandParser.commandParser(utility, args)) { + LOG.error("ScanEntrance::main exit, parser failed"); + ShowHelp.scanHelp(); + System.exit(EXIT_STATUS_EXCEPTION); + } + + if (!ScanVerify.commandVerify(utility)) { + LOG.error("ScanEntrance::main exit, verify failed"); + ShowHelp.scanHelp(); + System.exit(EXIT_STATUS_EXCEPTION); + } + + Scan scan = new Scan(); + if (!scan.scanProcess(utility)) { + LOG.error("ScanEntrance::main exit, compress failed"); + ShowHelp.scanHelp(); + System.exit(EXIT_STATUS_EXCEPTION); + } + + System.exit(EXIT_STATUS_NORMAL); + } +} \ No newline at end of file diff --git a/adapter/ohos/ScanVerify.java b/adapter/ohos/ScanVerify.java new file mode 100644 index 00000000..13ed0679 --- /dev/null +++ b/adapter/ohos/ScanVerify.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021 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.math.BigDecimal; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * scan comment,command parser. + * + */ +public class ScanVerify { + + static final String HAP = ".hap"; + static final String HSP = ".hsp"; + static final String APP = ".app"; + private static final String TRUE = "true"; + private static final String FALSE = "false"; + private static final String EMPTY_STRING = ""; + + private static final Log LOG = new Log(ScanVerify.class.toString()); + + /** + * if args valid. + * + * @param utility common data + * @return commandVerify if command valid. + */ + public static boolean commandVerify(Utility utility) { + if (utility == null) { + LOG.error("ScanVerify::commandVerify utility is null."); + return false; + } + + if (utility.getInput().isEmpty()) { + LOG.error("ScanVerify::commandVerify input is null."); + return false; + } + + if (!(utility.getInput().endsWith(HAP) || utility.getInput().endsWith(HSP) + || utility.getInput().endsWith(APP))) { + LOG.error("ScanVerify::commandVerify input is invalid!"); + return false; + } + + if (utility.getOutPath().isEmpty()) { + LOG.error("ScanVerify::commandVerify outPath is null."); + return false; + } + + if (!(TRUE.equals(utility.getStatDuplicate()) || FALSE.equals(utility.getStatDuplicate()))) { + LOG.error("ScanVerify::commandVerify statDuplicate is invalid! Must be true or false."); + return false; + } + + if (utility.getStatFileSize().isEmpty() || !checkNumber(utility.getStatFileSize()) + || new BigDecimal(utility.getStatFileSize()).compareTo(BigDecimal.ZERO) < 0 + || new BigDecimal(utility.getStatFileSize()).compareTo(new BigDecimal(Integer.MAX_VALUE)) > 0) { + LOG.error("ScanVerify::commandVerify statFileSize is invalid! Must be positiveInteger zero and less than integer max"); + return false; + } + + if (!(TRUE.equals(utility.getStatSuffix()) || FALSE.equals(utility.getStatSuffix()))) { + LOG.error("ScanVerify::commandVerify statSuffix is invalid! Must be true or false."); + return false; + } + + if (FALSE.equals(utility.getStatSuffix()) && FALSE.equals(utility.getStatDuplicate()) && + EMPTY_STRING.equals(utility.getStatFileSize())) { + LOG.error("ScanVerify::commandVerify stat parameter is null."); + } + + + return true; + } + + private static Boolean checkNumber(String str) { + Pattern pattern = Pattern.compile("[0-9]*"); + Matcher isNum = pattern.matcher(str); + return isNum.matches(); + } + +} diff --git a/adapter/ohos/ShowHelp.java b/adapter/ohos/ShowHelp.java index a0afce8c..f712387b 100644 --- a/adapter/ohos/ShowHelp.java +++ b/adapter/ohos/ShowHelp.java @@ -127,4 +127,36 @@ public interface ShowHelp { " --unpackapk default false; if true, unpack apk files from hap\n" + " in the app."); } + + /** + * content of scan command help menu. + */ + static void scanHelp() { + log.info("\nSTAT DUPLICATE USAGE:\n" + + "java -jar hmos_app_check_tool.jar --input [options] --out-path [option]\n" + + "--stat-duplicate [option]\n" + + "OPTIONS:\n" + + " --input not null must be hap or hsp or app.\n" + + " --out-path not null must be folder.\n" + + " --stat-duplicate not null default false; must be true or false.\n" + + " if true, count duplicate files.\n" + + "----------------------------------------------------------------------------------\n" + + "STAT FILE SIZE USAGE:\n" + + "java -jar hmos_app_check_tool.jar --input [options] --out-path [option]\n" + + "--stat-file-size [option]\n" + + "OPTIONS:\n" + + " --input not null must be hap or hsp or app.\n" + + " --out-path not null must be folder.\n" + + " --stat-file-size not null must be an number.\n" + + " count files exceeding the specified size.\n" + + "----------------------------------------------------------------------------------\n" + + "STAT SUFFIX USAGE:\n" + + "java -jar hmos_app_check_tool.jar --input [options] --out-path [option]\n" + + "--stat-suffix [option]\n" + + "OPTIONS:\n" + + " --input not null must be hap or hsp or app.\n" + + " --out-path not null must be folder.\n" + + " --stat-suffix not null default false; must be true or false;\n" + + " if true, calculate the proportion of various types of files."); + } } diff --git a/adapter/ohos/Utility.java b/adapter/ohos/Utility.java index 2f55295e..7eeabcfe 100644 --- a/adapter/ohos/Utility.java +++ b/adapter/ohos/Utility.java @@ -124,6 +124,10 @@ public class Utility { private String hqfList = ""; private String hspList = ""; private String inputList = ""; + private String input = ""; + private String statDuplicate = "false"; + private String statSuffix = "false"; + private String statFileSize = ""; public void setIsParse(boolean isParse) { this.isParse = isParse; @@ -804,4 +808,35 @@ public class Utility { public void setInputList(String inputList) { this.inputList = inputList; } + + public String getInput() { + return input; + } + + public void setInput(String input) { + this.input = getFormattedPath(input); + } + + public String getStatDuplicate() { + return statDuplicate; + } + + public void setStatDuplicate(String statDuplicate) { + this.statDuplicate = statDuplicate; + } + + public String getStatSuffix(){ + return statSuffix; + } + + public void setStatSuffix(String statSuffix) { + this.statSuffix = statSuffix; + } + public String getStatFileSize() { + return statFileSize; + } + + public void setStatFileSize(String statFileSize) { + this.statFileSize = statFileSize; + } } diff --git a/build.py b/build.py index 5a776bc8..d56ba64c 100755 --- a/build.py +++ b/build.py @@ -30,6 +30,7 @@ def main(): parser.add_argument('--haptobinOutput', required=True) parser.add_argument('--unpackOutput', required=True) parser.add_argument('--packOutput', required=True) + parser.add_argument('--checkOutput', required=True) parser.add_argument('--outpath', required=True) parser.add_argument('--toolchain', required=True) parser.add_argument('--compileTarget', required=True) @@ -37,6 +38,7 @@ def main(): print(args.haptobinOutput) print(args.unpackOutput) print(args.packOutput) + print(args.checkOutput) print(args.outpath) print(args.compileTarget) root_dir = os.path.dirname(os.path.realpath(__file__)) @@ -85,6 +87,16 @@ def main(): print(pack_out.decode('utf-8')) print(pack_err.decode('utf-8')) raise Exception("compile packing tool java class failed!") + + #compile app_check_tool.jar + check_tool_shell_path = os.path.join(root_dir, "checkTool.sh") + command_check = ['bash', check_tool_shell_path, root_dir, args.checkOutput, args.outpath, toolchain] + child_check = subprocess.Popen(command_check, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + check_out, check_err = child_check.communicate(timeout=time_out) + if child_check.returncode != 0: + print(check_out.decode('utf-8')) + print(check_err.decode('utf-8')) + raise Exception("compile check tool java class failed!") if __name__ == '__main__': sys.exit(main()) diff --git a/checkTool.sh b/checkTool.sh new file mode 100644 index 00000000..e06f1b56 --- /dev/null +++ b/checkTool.sh @@ -0,0 +1,113 @@ +#!/usr/bin/env bash +# Copyright (c) 2022 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. +set -e +root_path=$1 +pack_build_out_jar_path=$2 +pack_build_out_path=$3 +toolchain=$4 +final_path=$(pwd) + +jar_dir="jar" +pack_jar_file="app_check_tool.jar" +fastjson_jar_file="fastjson-1.2.83.jar" +jar_directory="${root_path}/jar" +pack_jar_path="${root_path}/${jar_dir}/${pack_jar_file}" +manifest_path="${root_path}/META-INF/check_tool/MANIFEST.MF" + +out_dir="${root_path}/out/${toolchain}/check_tool" +if [ -d "${out_dir}/ohos" ] + then + echo "${out_dir}/ohos exist" + else + mkdir -p "${out_dir}/ohos" +fi + +jar_path="${root_path}/jar" +fastjson_jar_path="${root_path}/jar/fastjson-1.2.83.jar" +java_suffix=".java" +java_collection="" +declare -a compile_class=( + "BundleException" + "CommandParser" + "ScanEntrance" + "Scan" + "ScanVerify" + "Log" + "PackFormatter" + "ShowHelp" + "Utility" + "FileUtils" + ) +compile_class_length=${#compile_class[@]} +for ((i=0; i<${compile_class_length};++i)) +do + java_collection="${java_collection} ${root_path}/adapter/ohos/${compile_class[$i]}${java_suffix}" +done +compile_command="javac -source 1.8 -target 1.8 -cp ${fastjson_jar_path} -d ${out_dir} ${java_collection}" +eval ${compile_command} + +temp_dir="$root_path/jar/temp_${toolchain}" +if [ -d "${temp_dir}" ] + then + echo "${temp_dir} exit" + else + mkdir ${temp_dir} +fi + +cd ${out_dir} +product_pack_jar_command="jar -cvfm ${temp_dir}/${pack_jar_file} ${manifest_path} ./ohos" +eval ${product_pack_jar_command} + +# merge app_packing_tool.jar and fastjson +cp ${fastjson_jar_path} "${temp_dir}/${fastjson_jar_file}" +detach_pack_jar_command="jar -xvf ${pack_jar_file}" +detach_fastjson_jar_command="jar -xvf ${fastjson_jar_file}" +cd ${temp_dir} +eval ${detach_pack_jar_command} +eval ${detach_fastjson_jar_command} +rm ${pack_jar_file} +rm ${fastjson_jar_file} + +cd ${jar_directory} +temp_pack_jar_dir="${root_path}/jar/packtool_${toolchain}" +temp_pack_jar_path="${root_path}/jar/packtool_${toolchain}/${pack_jar_file}" +merge_pack_fast_jar_command="jar -cvfm ${temp_pack_jar_path} ${manifest_path} -C ${temp_dir} ." +if [ -d "${temp_pack_jar_dir}" ] + then + echo "${temp_pack_jar_dir} exist" + else + mkdir -p ${temp_pack_jar_dir} +fi +eval ${merge_pack_fast_jar_command} + +# make out dir +final_pack_out_path="${final_path}/${pack_build_out_path}" +final_pack_jar_path="${final_path}/${pack_build_out_jar_path}" +if [ -d "$final_pack_out_path" ] + then + echo "${final_pack_out_path} exist" + else + mkdir -p ${final_pack_out_path} +fi +copy_command="cp ${temp_pack_jar_path} ${final_pack_jar_path}" +eval ${copy_command} +if [ -f "${pack_jar_file}"] + then + echo "${pack_jar_file} exist" + else + cp ${temp_pack_jar_path} ${pack_jar_file} +fi +rm -rf ${temp_pack_jar_dir} +rm -rf ${temp_dir} +rm -rf "${root_path}/out" diff --git a/packingtool.gni b/packingtool.gni index 9a9b38d3..bd21b05e 100755 --- a/packingtool.gni +++ b/packingtool.gni @@ -33,6 +33,8 @@ template("packing_tool") { rebase_path(outputs[2], root_build_dir), "--outpath", rebase_path(outputs[3], root_build_dir), + "--checkOutput", + rebase_path(outputs[4], root_build_dir), "--toolchain", current_toolchain, ] -- Gitee From aaf2b9796d97e3871a1e2f042f63147d9fcc6355 Mon Sep 17 00:00:00 2001 From: hupeixi Date: Mon, 20 Nov 2023 17:44:55 +0800 Subject: [PATCH 02/20] =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=A4=A7=E5=B0=8F?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hupeixi --- adapter/ohos/ScanVerify.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/adapter/ohos/ScanVerify.java b/adapter/ohos/ScanVerify.java index 13ed0679..c8c8ae52 100644 --- a/adapter/ohos/ScanVerify.java +++ b/adapter/ohos/ScanVerify.java @@ -67,11 +67,16 @@ public class ScanVerify { return false; } - if (utility.getStatFileSize().isEmpty() || !checkNumber(utility.getStatFileSize()) - || new BigDecimal(utility.getStatFileSize()).compareTo(BigDecimal.ZERO) < 0 - || new BigDecimal(utility.getStatFileSize()).compareTo(new BigDecimal(Integer.MAX_VALUE)) > 0) { - LOG.error("ScanVerify::commandVerify statFileSize is invalid! Must be positiveInteger zero and less than integer max"); - return false; + if (!utility.getStatFileSize().isEmpty()) { + if (!checkNumber(utility.getStatFileSize())) { + LOG.error("ScanVerify::commandVerify statFileSize is invalid! Must be positiveInteger zero and less than integer max"); + return false; + } + if (new BigDecimal(utility.getStatFileSize()).compareTo(BigDecimal.ZERO) < 0 + || new BigDecimal(utility.getStatFileSize()).compareTo(new BigDecimal(Integer.MAX_VALUE)) > 0) { + LOG.error("ScanVerify::commandVerify statFileSize is invalid! Must be positiveInteger zero and less than integer max"); + return false; + } } if (!(TRUE.equals(utility.getStatSuffix()) || FALSE.equals(utility.getStatSuffix()))) { -- Gitee From 77d2d866f7d676830b70e10b89f9b906cfc44c04 Mon Sep 17 00:00:00 2001 From: hupeixi Date: Tue, 21 Nov 2023 09:38:44 +0800 Subject: [PATCH 03/20] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hupeixi --- adapter/ohos/Scan.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adapter/ohos/Scan.java b/adapter/ohos/Scan.java index a93192fc..684aea3b 100644 --- a/adapter/ohos/Scan.java +++ b/adapter/ohos/Scan.java @@ -735,7 +735,7 @@ public class Scan { pathHtml = getPathListHtml(suffixResult.getPathList()); } String pathListHtml = EMPTY_STRING; - if (!pathHtml.isBlank()) { + if (!pathHtml.isEmpty() || !EMPTY_STRING.equals(pathHtml)) { pathListHtml = getHtmlRow(PATH_LIST, pathHtml); } String resultValue = getResultHtmlOfSuffix(suffixResult.getResult()); -- Gitee From 1d54dd8877a6bd7c382cd73870859d96015c702b Mon Sep 17 00:00:00 2001 From: hupeixi Date: Tue, 21 Nov 2023 09:42:19 +0800 Subject: [PATCH 04/20] =?UTF-8?q?=E5=88=A0=E9=99=A4CRLF=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hupeixi --- BUILD.gn | 65 ---------------------------- OAT.xml | 70 ------------------------------ build.py | 102 ------------------------------------------- checkTool.sh | 113 ------------------------------------------------ packingtool.gni | 54 ----------------------- 5 files changed, 404 deletions(-) delete mode 100755 BUILD.gn delete mode 100644 OAT.xml delete mode 100755 build.py delete mode 100644 checkTool.sh delete mode 100755 packingtool.gni diff --git a/BUILD.gn b/BUILD.gn deleted file mode 100755 index bc69cc23..00000000 --- a/BUILD.gn +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (c) 2021 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. - -import("//build/ohos.gni") -import("//developtools/packing_tool/packingtool.gni") - -packing_tool("packing_tool") { - sources = [ - "//developtools/packing_tool/adapter/ohos", - "//developtools/packing_tool/haptobin.sh", - "//developtools/packing_tool/packingTool.sh", - "//developtools/packing_tool/unpackingTool.sh", - "//developtools/packing_tool/checkTool.sh", - ] - outputs = [ - "${target_out_dir}/jar/haptobin_tool.jar", - "${target_out_dir}/jar/app_unpacking_tool.jar", - "${target_out_dir}/jar/app_packing_tool.jar", - "${target_out_dir}/jar", - "${target_out_dir}/jar/app_check_tool.jar", - ] -} - -ohos_prebuilt_etc("haptobin_tool") { - list = get_target_outputs(":packing_tool") - source = list[0] - deps = [ ":packing_tool" ] - install_enable = false -} - -ohos_prebuilt_etc("app_unpacking_tool") { - list = get_target_outputs(":packing_tool") - source = list[1] - deps = [ ":packing_tool" ] - install_enable = false -} - -ohos_prebuilt_etc("app_packing_tool") { - list = get_target_outputs(":packing_tool") - source = list[2] - deps = [ ":packing_tool" ] - install_enable = false -} - -ohos_prebuilt_etc("app_check_tool") { - list = get_target_outputs(":packing_tool") - source = list[3] - deps = [ ":packing_tool" ] - install_enable = false -} - -ohos_prebuilt_etc("fastjson-1.2.83") { - source = "jar/fastjson-1.2.83.jar" - install_enable = false -} diff --git a/OAT.xml b/OAT.xml deleted file mode 100644 index 85281534..00000000 --- a/OAT.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/build.py b/build.py deleted file mode 100755 index d56ba64c..00000000 --- a/build.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# Copyright (c) 2022 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. -""" -Archives a set of files. -""" - - -import os -import sys -import argparse -import subprocess -import re - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--haptobin', required=True) - parser.add_argument('--haptobinOutput', required=True) - parser.add_argument('--unpackOutput', required=True) - parser.add_argument('--packOutput', required=True) - parser.add_argument('--checkOutput', required=True) - parser.add_argument('--outpath', required=True) - parser.add_argument('--toolchain', required=True) - parser.add_argument('--compileTarget', required=True) - args = parser.parse_args() - print(args.haptobinOutput) - print(args.unpackOutput) - print(args.packOutput) - print(args.checkOutput) - print(args.outpath) - print(args.compileTarget) - root_dir = os.path.dirname(os.path.realpath(__file__)) - toolchain = args.toolchain - tool_list = toolchain.split(':') - toolchain = tool_list[-1] - toolchain += "_" + args.compileTarget - time_out = 5000 - - # compile haptobin_tool.jar - hap_to_bin_shell_path = os.path.join(root_dir, "haptobin.sh") - command_haptobin = ['bash', hap_to_bin_shell_path, root_dir, args.haptobinOutput, args.outpath, toolchain] - child_haptobin = subprocess.Popen(command_haptobin, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - haptobin_out, haptobin_err = child_haptobin.communicate(timeout=time_out) - if child_haptobin.returncode != 0: - print(haptobin_out.decode('utf-8')) - print(haptobin_err.decode('utf-8')) - raise Exception("compile haptobin java class failed!") - - # compile app_unpacking_tool.jar - version = subprocess.check_output(['javac', '-version'], stderr=subprocess.STDOUT) - version = version.decode('utf-8') - array = re.findall(r'\d+', version) - compatible_version = 8 - big_version = '' - if int(array[0]) > compatible_version: - big_version = 'true' - else: - big_version = 'false' - - unpack_tool_shell_path = os.path.join(root_dir, "unpackingTool.sh") - command_unpack = ['bash', unpack_tool_shell_path, root_dir, args.unpackOutput, args.outpath, big_version, toolchain] - child_unpack = subprocess.Popen(command_unpack, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - unpack_out, unpack_err = child_unpack.communicate(timeout=time_out) - if child_unpack.returncode != 0: - print(unpack_out.decode('utf-8')) - print(unpack_err.decode('utf-8')) - raise Exception("compile unapcking tool java class failed!") - - #compile app_packing_tool.jar - pack_tool_shell_path = os.path.join(root_dir, "packingTool.sh") - command_pack = ['bash', pack_tool_shell_path, root_dir, args.packOutput, args.outpath, toolchain] - child_pack = subprocess.Popen(command_pack, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - pack_out, pack_err = child_pack.communicate(timeout=time_out) - if child_pack.returncode != 0: - print(pack_out.decode('utf-8')) - print(pack_err.decode('utf-8')) - raise Exception("compile packing tool java class failed!") - - #compile app_check_tool.jar - check_tool_shell_path = os.path.join(root_dir, "checkTool.sh") - command_check = ['bash', check_tool_shell_path, root_dir, args.checkOutput, args.outpath, toolchain] - child_check = subprocess.Popen(command_check, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - check_out, check_err = child_check.communicate(timeout=time_out) - if child_check.returncode != 0: - print(check_out.decode('utf-8')) - print(check_err.decode('utf-8')) - raise Exception("compile check tool java class failed!") - -if __name__ == '__main__': - sys.exit(main()) diff --git a/checkTool.sh b/checkTool.sh deleted file mode 100644 index e06f1b56..00000000 --- a/checkTool.sh +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2022 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. -set -e -root_path=$1 -pack_build_out_jar_path=$2 -pack_build_out_path=$3 -toolchain=$4 -final_path=$(pwd) - -jar_dir="jar" -pack_jar_file="app_check_tool.jar" -fastjson_jar_file="fastjson-1.2.83.jar" -jar_directory="${root_path}/jar" -pack_jar_path="${root_path}/${jar_dir}/${pack_jar_file}" -manifest_path="${root_path}/META-INF/check_tool/MANIFEST.MF" - -out_dir="${root_path}/out/${toolchain}/check_tool" -if [ -d "${out_dir}/ohos" ] - then - echo "${out_dir}/ohos exist" - else - mkdir -p "${out_dir}/ohos" -fi - -jar_path="${root_path}/jar" -fastjson_jar_path="${root_path}/jar/fastjson-1.2.83.jar" -java_suffix=".java" -java_collection="" -declare -a compile_class=( - "BundleException" - "CommandParser" - "ScanEntrance" - "Scan" - "ScanVerify" - "Log" - "PackFormatter" - "ShowHelp" - "Utility" - "FileUtils" - ) -compile_class_length=${#compile_class[@]} -for ((i=0; i<${compile_class_length};++i)) -do - java_collection="${java_collection} ${root_path}/adapter/ohos/${compile_class[$i]}${java_suffix}" -done -compile_command="javac -source 1.8 -target 1.8 -cp ${fastjson_jar_path} -d ${out_dir} ${java_collection}" -eval ${compile_command} - -temp_dir="$root_path/jar/temp_${toolchain}" -if [ -d "${temp_dir}" ] - then - echo "${temp_dir} exit" - else - mkdir ${temp_dir} -fi - -cd ${out_dir} -product_pack_jar_command="jar -cvfm ${temp_dir}/${pack_jar_file} ${manifest_path} ./ohos" -eval ${product_pack_jar_command} - -# merge app_packing_tool.jar and fastjson -cp ${fastjson_jar_path} "${temp_dir}/${fastjson_jar_file}" -detach_pack_jar_command="jar -xvf ${pack_jar_file}" -detach_fastjson_jar_command="jar -xvf ${fastjson_jar_file}" -cd ${temp_dir} -eval ${detach_pack_jar_command} -eval ${detach_fastjson_jar_command} -rm ${pack_jar_file} -rm ${fastjson_jar_file} - -cd ${jar_directory} -temp_pack_jar_dir="${root_path}/jar/packtool_${toolchain}" -temp_pack_jar_path="${root_path}/jar/packtool_${toolchain}/${pack_jar_file}" -merge_pack_fast_jar_command="jar -cvfm ${temp_pack_jar_path} ${manifest_path} -C ${temp_dir} ." -if [ -d "${temp_pack_jar_dir}" ] - then - echo "${temp_pack_jar_dir} exist" - else - mkdir -p ${temp_pack_jar_dir} -fi -eval ${merge_pack_fast_jar_command} - -# make out dir -final_pack_out_path="${final_path}/${pack_build_out_path}" -final_pack_jar_path="${final_path}/${pack_build_out_jar_path}" -if [ -d "$final_pack_out_path" ] - then - echo "${final_pack_out_path} exist" - else - mkdir -p ${final_pack_out_path} -fi -copy_command="cp ${temp_pack_jar_path} ${final_pack_jar_path}" -eval ${copy_command} -if [ -f "${pack_jar_file}"] - then - echo "${pack_jar_file} exist" - else - cp ${temp_pack_jar_path} ${pack_jar_file} -fi -rm -rf ${temp_pack_jar_dir} -rm -rf ${temp_dir} -rm -rf "${root_path}/out" diff --git a/packingtool.gni b/packingtool.gni deleted file mode 100755 index bd21b05e..00000000 --- a/packingtool.gni +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2022 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. - -import("//build/config/python.gni") -import("//build/templates/metadata/module_info.gni") - -template("packing_tool") { - action_with_pydeps(target_name) { - forward_variables_from(invoker, - [ - "sources", - "outputs", - ]) - script = "//developtools/packing_tool/build.py" - args = [ - "--haptobin", - rebase_path(sources[0], root_build_dir), - "--haptobinOutput", - rebase_path(outputs[0], root_build_dir), - "--unpackOutput", - rebase_path(outputs[1], root_build_dir), - "--packOutput", - rebase_path(outputs[2], root_build_dir), - "--outpath", - rebase_path(outputs[3], root_build_dir), - "--checkOutput", - rebase_path(outputs[4], root_build_dir), - "--toolchain", - current_toolchain, - ] - if (build_ohos_sdk) { - args += [ - "--compileTarget", - "sdk", - ] - } else { - args += [ - "--compileTarget", - "image", - ] - } - print(args) - } -} -- Gitee From 8a17d57add63cb49abf2fcf672ed7619d949bdb3 Mon Sep 17 00:00:00 2001 From: hupeixi Date: Tue, 21 Nov 2023 09:44:08 +0800 Subject: [PATCH 05/20] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20LF=20=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hupeixi --- BUILD.gn | 65 ++++++++++++++++++++++++++++ OAT.xml | 70 ++++++++++++++++++++++++++++++ build.py | 102 +++++++++++++++++++++++++++++++++++++++++++ checkTool.sh | 113 ++++++++++++++++++++++++++++++++++++++++++++++++ packingtool.gni | 54 +++++++++++++++++++++++ 5 files changed, 404 insertions(+) create mode 100644 BUILD.gn create mode 100644 OAT.xml create mode 100644 build.py create mode 100644 checkTool.sh create mode 100644 packingtool.gni diff --git a/BUILD.gn b/BUILD.gn new file mode 100644 index 00000000..bc69cc23 --- /dev/null +++ b/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (c) 2021 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. + +import("//build/ohos.gni") +import("//developtools/packing_tool/packingtool.gni") + +packing_tool("packing_tool") { + sources = [ + "//developtools/packing_tool/adapter/ohos", + "//developtools/packing_tool/haptobin.sh", + "//developtools/packing_tool/packingTool.sh", + "//developtools/packing_tool/unpackingTool.sh", + "//developtools/packing_tool/checkTool.sh", + ] + outputs = [ + "${target_out_dir}/jar/haptobin_tool.jar", + "${target_out_dir}/jar/app_unpacking_tool.jar", + "${target_out_dir}/jar/app_packing_tool.jar", + "${target_out_dir}/jar", + "${target_out_dir}/jar/app_check_tool.jar", + ] +} + +ohos_prebuilt_etc("haptobin_tool") { + list = get_target_outputs(":packing_tool") + source = list[0] + deps = [ ":packing_tool" ] + install_enable = false +} + +ohos_prebuilt_etc("app_unpacking_tool") { + list = get_target_outputs(":packing_tool") + source = list[1] + deps = [ ":packing_tool" ] + install_enable = false +} + +ohos_prebuilt_etc("app_packing_tool") { + list = get_target_outputs(":packing_tool") + source = list[2] + deps = [ ":packing_tool" ] + install_enable = false +} + +ohos_prebuilt_etc("app_check_tool") { + list = get_target_outputs(":packing_tool") + source = list[3] + deps = [ ":packing_tool" ] + install_enable = false +} + +ohos_prebuilt_etc("fastjson-1.2.83") { + source = "jar/fastjson-1.2.83.jar" + install_enable = false +} diff --git a/OAT.xml b/OAT.xml new file mode 100644 index 00000000..85281534 --- /dev/null +++ b/OAT.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build.py b/build.py new file mode 100644 index 00000000..d56ba64c --- /dev/null +++ b/build.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2022 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. +""" +Archives a set of files. +""" + + +import os +import sys +import argparse +import subprocess +import re + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--haptobin', required=True) + parser.add_argument('--haptobinOutput', required=True) + parser.add_argument('--unpackOutput', required=True) + parser.add_argument('--packOutput', required=True) + parser.add_argument('--checkOutput', required=True) + parser.add_argument('--outpath', required=True) + parser.add_argument('--toolchain', required=True) + parser.add_argument('--compileTarget', required=True) + args = parser.parse_args() + print(args.haptobinOutput) + print(args.unpackOutput) + print(args.packOutput) + print(args.checkOutput) + print(args.outpath) + print(args.compileTarget) + root_dir = os.path.dirname(os.path.realpath(__file__)) + toolchain = args.toolchain + tool_list = toolchain.split(':') + toolchain = tool_list[-1] + toolchain += "_" + args.compileTarget + time_out = 5000 + + # compile haptobin_tool.jar + hap_to_bin_shell_path = os.path.join(root_dir, "haptobin.sh") + command_haptobin = ['bash', hap_to_bin_shell_path, root_dir, args.haptobinOutput, args.outpath, toolchain] + child_haptobin = subprocess.Popen(command_haptobin, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + haptobin_out, haptobin_err = child_haptobin.communicate(timeout=time_out) + if child_haptobin.returncode != 0: + print(haptobin_out.decode('utf-8')) + print(haptobin_err.decode('utf-8')) + raise Exception("compile haptobin java class failed!") + + # compile app_unpacking_tool.jar + version = subprocess.check_output(['javac', '-version'], stderr=subprocess.STDOUT) + version = version.decode('utf-8') + array = re.findall(r'\d+', version) + compatible_version = 8 + big_version = '' + if int(array[0]) > compatible_version: + big_version = 'true' + else: + big_version = 'false' + + unpack_tool_shell_path = os.path.join(root_dir, "unpackingTool.sh") + command_unpack = ['bash', unpack_tool_shell_path, root_dir, args.unpackOutput, args.outpath, big_version, toolchain] + child_unpack = subprocess.Popen(command_unpack, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + unpack_out, unpack_err = child_unpack.communicate(timeout=time_out) + if child_unpack.returncode != 0: + print(unpack_out.decode('utf-8')) + print(unpack_err.decode('utf-8')) + raise Exception("compile unapcking tool java class failed!") + + #compile app_packing_tool.jar + pack_tool_shell_path = os.path.join(root_dir, "packingTool.sh") + command_pack = ['bash', pack_tool_shell_path, root_dir, args.packOutput, args.outpath, toolchain] + child_pack = subprocess.Popen(command_pack, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + pack_out, pack_err = child_pack.communicate(timeout=time_out) + if child_pack.returncode != 0: + print(pack_out.decode('utf-8')) + print(pack_err.decode('utf-8')) + raise Exception("compile packing tool java class failed!") + + #compile app_check_tool.jar + check_tool_shell_path = os.path.join(root_dir, "checkTool.sh") + command_check = ['bash', check_tool_shell_path, root_dir, args.checkOutput, args.outpath, toolchain] + child_check = subprocess.Popen(command_check, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + check_out, check_err = child_check.communicate(timeout=time_out) + if child_check.returncode != 0: + print(check_out.decode('utf-8')) + print(check_err.decode('utf-8')) + raise Exception("compile check tool java class failed!") + +if __name__ == '__main__': + sys.exit(main()) diff --git a/checkTool.sh b/checkTool.sh new file mode 100644 index 00000000..e06f1b56 --- /dev/null +++ b/checkTool.sh @@ -0,0 +1,113 @@ +#!/usr/bin/env bash +# Copyright (c) 2022 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. +set -e +root_path=$1 +pack_build_out_jar_path=$2 +pack_build_out_path=$3 +toolchain=$4 +final_path=$(pwd) + +jar_dir="jar" +pack_jar_file="app_check_tool.jar" +fastjson_jar_file="fastjson-1.2.83.jar" +jar_directory="${root_path}/jar" +pack_jar_path="${root_path}/${jar_dir}/${pack_jar_file}" +manifest_path="${root_path}/META-INF/check_tool/MANIFEST.MF" + +out_dir="${root_path}/out/${toolchain}/check_tool" +if [ -d "${out_dir}/ohos" ] + then + echo "${out_dir}/ohos exist" + else + mkdir -p "${out_dir}/ohos" +fi + +jar_path="${root_path}/jar" +fastjson_jar_path="${root_path}/jar/fastjson-1.2.83.jar" +java_suffix=".java" +java_collection="" +declare -a compile_class=( + "BundleException" + "CommandParser" + "ScanEntrance" + "Scan" + "ScanVerify" + "Log" + "PackFormatter" + "ShowHelp" + "Utility" + "FileUtils" + ) +compile_class_length=${#compile_class[@]} +for ((i=0; i<${compile_class_length};++i)) +do + java_collection="${java_collection} ${root_path}/adapter/ohos/${compile_class[$i]}${java_suffix}" +done +compile_command="javac -source 1.8 -target 1.8 -cp ${fastjson_jar_path} -d ${out_dir} ${java_collection}" +eval ${compile_command} + +temp_dir="$root_path/jar/temp_${toolchain}" +if [ -d "${temp_dir}" ] + then + echo "${temp_dir} exit" + else + mkdir ${temp_dir} +fi + +cd ${out_dir} +product_pack_jar_command="jar -cvfm ${temp_dir}/${pack_jar_file} ${manifest_path} ./ohos" +eval ${product_pack_jar_command} + +# merge app_packing_tool.jar and fastjson +cp ${fastjson_jar_path} "${temp_dir}/${fastjson_jar_file}" +detach_pack_jar_command="jar -xvf ${pack_jar_file}" +detach_fastjson_jar_command="jar -xvf ${fastjson_jar_file}" +cd ${temp_dir} +eval ${detach_pack_jar_command} +eval ${detach_fastjson_jar_command} +rm ${pack_jar_file} +rm ${fastjson_jar_file} + +cd ${jar_directory} +temp_pack_jar_dir="${root_path}/jar/packtool_${toolchain}" +temp_pack_jar_path="${root_path}/jar/packtool_${toolchain}/${pack_jar_file}" +merge_pack_fast_jar_command="jar -cvfm ${temp_pack_jar_path} ${manifest_path} -C ${temp_dir} ." +if [ -d "${temp_pack_jar_dir}" ] + then + echo "${temp_pack_jar_dir} exist" + else + mkdir -p ${temp_pack_jar_dir} +fi +eval ${merge_pack_fast_jar_command} + +# make out dir +final_pack_out_path="${final_path}/${pack_build_out_path}" +final_pack_jar_path="${final_path}/${pack_build_out_jar_path}" +if [ -d "$final_pack_out_path" ] + then + echo "${final_pack_out_path} exist" + else + mkdir -p ${final_pack_out_path} +fi +copy_command="cp ${temp_pack_jar_path} ${final_pack_jar_path}" +eval ${copy_command} +if [ -f "${pack_jar_file}"] + then + echo "${pack_jar_file} exist" + else + cp ${temp_pack_jar_path} ${pack_jar_file} +fi +rm -rf ${temp_pack_jar_dir} +rm -rf ${temp_dir} +rm -rf "${root_path}/out" diff --git a/packingtool.gni b/packingtool.gni new file mode 100644 index 00000000..bd21b05e --- /dev/null +++ b/packingtool.gni @@ -0,0 +1,54 @@ +# Copyright (c) 2022 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. + +import("//build/config/python.gni") +import("//build/templates/metadata/module_info.gni") + +template("packing_tool") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "sources", + "outputs", + ]) + script = "//developtools/packing_tool/build.py" + args = [ + "--haptobin", + rebase_path(sources[0], root_build_dir), + "--haptobinOutput", + rebase_path(outputs[0], root_build_dir), + "--unpackOutput", + rebase_path(outputs[1], root_build_dir), + "--packOutput", + rebase_path(outputs[2], root_build_dir), + "--outpath", + rebase_path(outputs[3], root_build_dir), + "--checkOutput", + rebase_path(outputs[4], root_build_dir), + "--toolchain", + current_toolchain, + ] + if (build_ohos_sdk) { + args += [ + "--compileTarget", + "sdk", + ] + } else { + args += [ + "--compileTarget", + "image", + ] + } + print(args) + } +} -- Gitee From 1171e398603a3f8f36db0ebbac0a8aeeecb66e88 Mon Sep 17 00:00:00 2001 From: hupeixi Date: Tue, 21 Nov 2023 14:01:19 +0800 Subject: [PATCH 06/20] =?UTF-8?q?=E4=BF=AE=E6=94=B9GN=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hupeixi --- BUILD.gn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD.gn b/BUILD.gn index bc69cc23..569c1904 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -17,10 +17,10 @@ import("//developtools/packing_tool/packingtool.gni") packing_tool("packing_tool") { sources = [ "//developtools/packing_tool/adapter/ohos", + "//developtools/packing_tool/checkTool.sh", "//developtools/packing_tool/haptobin.sh", "//developtools/packing_tool/packingTool.sh", "//developtools/packing_tool/unpackingTool.sh", - "//developtools/packing_tool/checkTool.sh", ] outputs = [ "${target_out_dir}/jar/haptobin_tool.jar", -- Gitee From ae3df759a8bf4acf34b4c51f629dd93b25a7c543 Mon Sep 17 00:00:00 2001 From: hupeixi Date: Tue, 21 Nov 2023 16:50:37 +0800 Subject: [PATCH 07/20] =?UTF-8?q?=E4=BF=AE=E6=94=B9py3=EF=BC=8C=E8=BF=87?= =?UTF-8?q?=E6=BB=A4=E9=87=8D=E5=A4=8D=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hupeixi --- adapter/ohos/Scan.java | 9 ++++++++- build.py | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/adapter/ohos/Scan.java b/adapter/ohos/Scan.java index 684aea3b..7a5c3fd6 100644 --- a/adapter/ohos/Scan.java +++ b/adapter/ohos/Scan.java @@ -619,7 +619,14 @@ public class Scan { LOG.error("Compressor::compressHapAddition create target file parent directory failed."); } } - duplicateResult.setResult(resList); + List filterList = new ArrayList<>(); + for (ParamModel m: resList) { + List files = m.getFiles(); + if (files.size() > 1) { + filterList.add(m); + } + } + duplicateResult.setResult(filterList); String jsonStr = JSON.toJSONString(duplicateResult, new SerializerFeature[]{ SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteDateUseDateFormat}); diff --git a/build.py b/build.py index d56ba64c..8714e749 100644 --- a/build.py +++ b/build.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (c) 2022 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); -- Gitee From ea8871b685512cec7d5875842357a55a34a8d4e6 Mon Sep 17 00:00:00 2001 From: hupeixi Date: Wed, 22 Nov 2023 14:35:57 +0800 Subject: [PATCH 08/20] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=89=AB=E6=8F=8F?= =?UTF-8?q?=E8=AF=B4=E6=98=8E=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hupeixi --- adapter/scanner/README_zh.md | 169 +++++++++++++++++++++++++++ adapter/scanner/image/construct.png | Bin 0 -> 46374 bytes adapter/scanner/image/duplicate.html | 57 +++++++++ adapter/scanner/image/duplicate.json | 15 +++ adapter/scanner/image/filesize.html | 41 +++++++ adapter/scanner/image/filesize.json | 11 ++ adapter/scanner/image/suffix.html | 75 ++++++++++++ adapter/scanner/image/suffix.json | 32 +++++ 8 files changed, 400 insertions(+) create mode 100644 adapter/scanner/README_zh.md create mode 100644 adapter/scanner/image/construct.png create mode 100644 adapter/scanner/image/duplicate.html create mode 100644 adapter/scanner/image/duplicate.json create mode 100644 adapter/scanner/image/filesize.html create mode 100644 adapter/scanner/image/filesize.json create mode 100644 adapter/scanner/image/suffix.html create mode 100644 adapter/scanner/image/suffix.json diff --git a/adapter/scanner/README_zh.md b/adapter/scanner/README_zh.md new file mode 100644 index 00000000..4f532cef --- /dev/null +++ b/adapter/scanner/README_zh.md @@ -0,0 +1,169 @@ +# 扫描工具使用说明 + +## 简介 + +app_check_tool用于扫描指定路径的hap、hsp、app包,统计重复文件、统计超出指定大小的文件、统计各类型文件大小占比,输出html结果文件和json结果文件。 + +### 扫描工具系统架构图 + +![](image/construct.png) + +### 1. 扫描工具使用指令 + +#### 1.1 示例 + +- 统计重复文件命令示例: + + +``` +java -jar app_check_tool.jar --input