1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package ohos; 17 18 import com.alibaba.fastjson.JSONObject; 19 20 import java.io.IOException; 21 import java.io.RandomAccessFile; 22 import java.util.Optional; 23 24 /** 25 * bin file to hap tool main class. 26 * 27 */ 28 public class CollectBinInfo { 29 private static final String JSON_FILE_NAME = "config.json"; 30 private static final String PROFILE_KEY = "app"; 31 private static final String VERSION_KEY = "version"; 32 private static final String CODE_KEY = "code"; 33 private static final String BIN_PATH = "--bin-path"; 34 private static final String VERSION_CODE = "--version-code"; 35 private static final int PARA_COUNT = 3; 36 private static final int MAGIC_NUMBER = 190; 37 private static final int INT_LENGTH = 4; 38 private static final int LONG_LENGTH = 8; 39 private static int bundleNameLen = 0; 40 41 /** 42 * get versionCode from bin file 43 * 44 * @param binPath: bin path 45 * @return versionCode 46 */ getVersionCode(final String binPath)47 public static String getVersionCode(final String binPath) { 48 String versionCode = ""; 49 if (!FileUtils.checkFileIsExists(binPath)) { 50 return versionCode; 51 } 52 53 Optional<String> absBinPath = FileUtils.getFormatedPath(binPath); 54 RandomAccessFile binStream = null; 55 try { 56 binStream = new RandomAccessFile(absBinPath.get(), "r"); 57 if (!readBinFileHeader(binStream)) { 58 return versionCode; 59 } 60 long fileDataPos = 1 + INT_LENGTH + bundleNameLen; 61 byte [] fileDataByte = readBinFileData(JSON_FILE_NAME, binStream, fileDataPos); 62 if (fileDataByte == null) { 63 return versionCode; 64 } 65 String fileData = new String(fileDataByte, "UTF-8"); 66 JSONObject object = JSONObject.parseObject(fileData); 67 if (object == null || !object.containsKey(PROFILE_KEY)) { 68 return versionCode; 69 } 70 object = object.getJSONObject(PROFILE_KEY); 71 if (object == null || !object.containsKey(VERSION_KEY)) { 72 return versionCode; 73 } 74 object = object.getJSONObject(VERSION_KEY); 75 if (object != null) { 76 versionCode = object.getInteger(CODE_KEY).toString(); 77 } 78 return versionCode; 79 } catch (IOException msg) { 80 return versionCode; 81 } finally { 82 if (binStream != null) { 83 FileUtils.closeStream(binStream); 84 } 85 } 86 } 87 88 /** 89 * read bin file header 90 * 91 * @param binStream: bin randAccessFileStream 92 * @return true or false 93 */ readBinFileHeader(RandomAccessFile binStream)94 private static boolean readBinFileHeader(RandomAccessFile binStream) { 95 try { 96 byte magic = binStream.readByte(); 97 if ((magic & 0xff) != MAGIC_NUMBER) { 98 return false; 99 } 100 bundleNameLen = binStream.readInt(); 101 if (bundleNameLen >= 0) { 102 byte [] bundleNameByte = new byte[bundleNameLen]; 103 binStream.readFully(bundleNameByte, 0, bundleNameLen); 104 return true; 105 } 106 return false; 107 } catch (IOException msg) { 108 return false; 109 } 110 } 111 112 /** 113 * read bin file data 114 * 115 * @param fileName: file name 116 * @param binStream: bin randAccessFileStream 117 * @param fileDataPos: position which begin to read file data 118 * @return fileData byte 119 */ readBinFileData(final String fileName, RandomAccessFile binStream, long fileDataPos)120 private static byte [] readBinFileData(final String fileName, RandomAccessFile binStream, long fileDataPos) { 121 try { 122 long fileSize = binStream.length(); 123 long pos = fileDataPos; 124 while (pos < fileSize) { 125 int nameLen = binStream.readInt(); 126 if (nameLen <= 0) { 127 return null; 128 } 129 byte [] fileNameByte = new byte[nameLen]; 130 binStream.readFully(fileNameByte, 0, nameLen); 131 int relativePathLen = binStream.readInt(); 132 if (relativePathLen < 0) { 133 return null; 134 } 135 binStream.seek(pos + INT_LENGTH + nameLen + INT_LENGTH + relativePathLen); 136 long dataLen = binStream.readLong(); 137 if (dataLen > Integer.MAX_VALUE || dataLen <= 0) { 138 return null; 139 } 140 byte [] fileData = new byte[(int) dataLen]; 141 binStream.readFully(fileData, 0, (int) dataLen); 142 pos = pos + INT_LENGTH + nameLen + INT_LENGTH + relativePathLen + LONG_LENGTH + dataLen; 143 String name = new String(fileNameByte, "UTF-8"); 144 if (name.equals(fileName)) { 145 return fileData; 146 } 147 } 148 return null; 149 } catch (IOException msg) { 150 return null; 151 } 152 } 153 154 /** 155 * tool main function. 156 * 157 * @param args command line 158 */ main(String[] args)159 public static void main(String[] args) { 160 if (args.length != PARA_COUNT) { 161 return; 162 } 163 String binPath = ""; 164 int count = 0; 165 boolean versionFlag = false; 166 for (String para : args) { 167 if (BIN_PATH.equals(para) && count < args.length - 1) { 168 binPath = args[count + 1]; 169 } 170 if (VERSION_CODE.equals(para) && count < args.length) { 171 versionFlag = true; 172 } 173 count++; 174 } 175 if (!binPath.isEmpty() && versionFlag) { 176 String versionCode = getVersionCode(binPath); 177 } 178 } 179 }