• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 #include "StageContext.h"
16 #include <sstream>
17 #include <fstream>
18 #include <cctype>
19 #include <algorithm>
20 #include "JsonReader.h"
21 #include "FileSystem.h"
22 #include "TraceTool.h"
23 #include "PreviewerEngineLog.h"
24 #include "CommandParser.h"
25 #include "zlib.h"
26 #include "contrib/minizip/unzip.h"
27 
28 namespace OHOS::Ide {
GetInstance()29 StageContext& StageContext::GetInstance()
30 {
31     static StageContext instance;
32     return instance;
33 }
34 
ReadFileContents(const std::string & filePath) const35 const std::optional<std::vector<uint8_t>> StageContext::ReadFileContents(const std::string& filePath) const
36 {
37     if (!FileSystem::IsFileExists(filePath)) {
38         ELOG("file %s is not exist.", filePath.c_str());
39         return std::nullopt;
40     }
41     std::ifstream file(filePath, std::ios::binary | std::ios::ate);
42     if (!file) {
43         ELOG("open file %s failed.", filePath.c_str());
44         return std::nullopt;
45     }
46     std::streamsize fileSize = file.tellg();
47     file.seekg(0, std::ios::beg);
48     std::vector<uint8_t> data(fileSize);
49     if (file.read(reinterpret_cast<char*>(data.data()), fileSize)) {
50         return data;
51     } else {
52         ELOG("read file %s failed.", filePath.c_str());
53         return std::nullopt;
54     }
55 }
56 
SetLoaderJsonPath(const std::string & assetPath)57 void StageContext::SetLoaderJsonPath(const std::string& assetPath)
58 {
59     loaderJsonPath = FileSystem::NormalizePath(assetPath);
60     if (loaderJsonPath.empty() || !FileSystem::IsFileExists(loaderJsonPath)) {
61         ELOG("the loaderJsonPath %s is not exist.", loaderJsonPath.c_str());
62         return;
63     }
64     ILOG("set loaderJsonPath: %s successed.", loaderJsonPath.c_str());
65 }
66 
SetHosSdkPath(const std::string & hosSdkPathValue)67 void StageContext::SetHosSdkPath(const std::string& hosSdkPathValue)
68 {
69     this->hosSdkPath = hosSdkPathValue;
70 }
71 
GetModulePathMapFromLoaderJson()72 void StageContext::GetModulePathMapFromLoaderJson()
73 {
74     if (!FileSystem::IsFileExists(loaderJsonPath)) {
75         ELOG("the loaderJsonPath is not exist.");
76         return;
77     }
78     std::string jsonStr = JsonReader::ReadFile(loaderJsonPath);
79     Json2::Value rootJson = JsonReader::ParseJsonData2(jsonStr);
80     if (rootJson.IsNull() || !rootJson.IsValid()) {
81         ELOG("Get loader.json content failed.");
82         return;
83     }
84     if (!rootJson.IsMember("modulePathMap") || !rootJson.IsMember("harNameOhmMap") ||
85         !rootJson.IsMember("projectRootPath") || !rootJson.IsMember("hspResourcesMap")) {
86         ELOG("Don't find some necessary node in loader.json.");
87         return;
88     }
89     Json2::Value jsonObj = rootJson["modulePathMap"];
90     for (const auto& key : jsonObj.GetMemberNames()) {
91         modulePathMap[key] = jsonObj[key].AsString();
92     }
93     Json2::Value jsonObjOhm = rootJson["harNameOhmMap"];
94     if (rootJson.IsMember("hspNameOhmMap")) {
95         if (!rootJson["hspNameOhmMap"].IsNull() && rootJson["hspNameOhmMap"].IsValid()) {
96             ILOG("hspNameOhmMap is valid");
97             jsonObjOhm = rootJson["hspNameOhmMap"];
98         }
99     }
100     for (const auto& key : jsonObjOhm.GetMemberNames()) {
101         hspNameOhmMap[key] = jsonObjOhm[key].AsString();
102     }
103     projectRootPath = rootJson["projectRootPath"].AsString();
104     if (rootJson.IsMember("buildConfigPath")) {
105         buildConfigPath = rootJson["buildConfigPath"].AsString();
106     }
107     Json2::Value jsonObjResources = rootJson["hspResourcesMap"];
108     for (const auto& key : jsonObjResources.GetMemberNames()) {
109         hspResourcesMap[key] = jsonObjResources[key].AsString();
110     }
111 }
112 
GetHspAceModuleBuild(const std::string & hspConfigPath)113 std::string StageContext::GetHspAceModuleBuild(const std::string& hspConfigPath)
114 {
115     if (!FileSystem::IsFileExists(hspConfigPath)) {
116         ELOG("hspConfigPath: %s is not exist.", hspConfigPath.c_str());
117         return "";
118     }
119     std::string jsonStr = JsonReader::ReadFile(hspConfigPath);
120     Json2::Value rootJson = JsonReader::ParseJsonData2(jsonStr);
121     if (rootJson.IsNull() || !rootJson.IsValid()) {
122         ELOG("Get hsp buildConfig.json content failed.");
123         return "";
124     }
125     if (!rootJson.IsMember("aceModuleBuild")) {
126         ELOG("Don't find aceModuleBuild node in hsp buildConfig.json.");
127         return "";
128     }
129     return rootJson["aceModuleBuild"].AsString();
130 }
131 
ReleaseHspBuffers()132 void StageContext::ReleaseHspBuffers()
133 {
134     for (std::vector<uint8_t>* ptr : hspBufferPtrsVec) {
135         if (ptr) {
136             delete ptr;
137         }
138     }
139     hspBufferPtrsVec.clear();
140     ILOG("ReleaseHspBuffers finished.");
141 }
142 
GetModulePathMap() const143 std::map<std::string, std::string> StageContext::GetModulePathMap() const
144 {
145     return modulePathMap;
146 }
147 
GetModuleBuffer(const std::string & inputPath)148 std::vector<uint8_t>* StageContext::GetModuleBuffer(const std::string& inputPath)
149 {
150     ILOG("inputPath is:%s.", inputPath.c_str());
151     TraceTool::GetInstance().HandleTrace("HSP is loaded");
152     std::string spliter = "/";
153     size_t pos = inputPath.rfind(spliter);
154     if (pos == std::string::npos) {
155         ELOG("inputPath: %s format error.", inputPath.c_str());
156         return nullptr;
157     }
158     std::string bundleName = inputPath.substr(0, pos);
159     ILOG("bundleName is:%s.", bundleName.c_str());
160     if (bundleName.empty()) {
161         ELOG("bundleName is empty.");
162         return nullptr;
163     }
164     std::string moduleName = inputPath.substr(pos + spliter.size());
165     ILOG("moduleName is:%s.", moduleName.c_str());
166     if (modulePathMap.empty()) {
167         ELOG("modulePathMap is empty.");
168         return nullptr;
169     }
170     if (bundleName == localBundleName) { // local hsp
171         if (modulePathMap.count(moduleName) > 0) { // exist local hsp
172             std::vector<uint8_t>* buffer = GetLocalModuleBuffer(moduleName);
173             if (buffer == nullptr) {
174                 return GetCloudModuleBuffer(moduleName);
175             }
176             return buffer;
177         } else { // local hsp not exist, load cloud hsp
178             ILOG("cloud hsp bundleName is same as the local project.");
179             return GetCloudModuleBuffer(moduleName);
180         }
181     } else {
182         // 先找三方hsp,再找系统hsp
183         std::vector<uint8_t>* buf = GetCloudModuleBuffer(moduleName);
184         if (buf) { // cloud hsp
185             return buf;
186         } else { // system hsp
187             std::vector<uint8_t>* buf = GetSystemModuleBuffer(inputPath, moduleName);
188             ILOG("system hsp buf size is %d", buf->size());
189             return buf;
190         }
191     }
192 }
193 
GetLocalModuleBuffer(const std::string & moduleName)194 std::vector<uint8_t>* StageContext::GetLocalModuleBuffer(const std::string& moduleName)
195 {
196     std::string modulePath = StageContext::GetInstance().modulePathMap[moduleName];
197     if (modulePath.empty()) {
198         ELOG("modulePath is empty.");
199         return nullptr;
200     }
201     ILOG("get modulePath: %s successed.", modulePath.c_str());
202     if (!FileSystem::IsDirectoryExists(modulePath)) {
203         ELOG("don't find moduleName: %s in modulePathMap from loader.json.", moduleName.c_str());
204         return nullptr;
205     }
206     if (ContainsRelativePath(modulePath)) {
207         ELOG("modulePath format error: %s.", modulePath.c_str());
208         return nullptr;
209     }
210     std::string separator = FileSystem::GetSeparator();
211     // 读取hsp的.preview/config/buildConfig.json获取aceModuleBuild值就是hsp的modules.abc所在文件夹
212     std::string hspConfigPath = modulePath + separator + ".preview" + separator + "config" +
213         separator + "buildConfig.json";
214     if (!buildConfigPath.empty()) {
215         ILOG("buildConfigPath is not empty.");
216         hspConfigPath = modulePath + separator + buildConfigPath;
217     }
218     std::string abcDir = GetHspAceModuleBuild(hspConfigPath);
219     if (!FileSystem::IsDirectoryExists(abcDir)) {
220         ELOG("the abcDir:%s is not exist.", abcDir.c_str());
221         return nullptr;
222     }
223     std::string abcPath = abcDir + separator + "modules.abc";
224     if (!FileSystem::IsFileExists(abcPath)) {
225         ELOG("the abcPath:%s is not exist.", abcPath.c_str());
226         return nullptr;
227     }
228     ILOG("get modules.abc path: %s successed.", abcPath.c_str());
229     std::optional<std::vector<uint8_t>> opt = ReadFileContents(abcPath);
230     if (!opt.has_value()) {
231         ELOG("read modules.abc buffer failed.");
232         return nullptr;
233     }
234     std::vector<uint8_t> *buf = new(std::nothrow) std::vector<uint8_t>(opt.value());
235     if (!buf) {
236         ELOG("Memory allocation failed: buf.");
237     }
238     hspBufferPtrsVec.push_back(buf);
239     return buf;
240 }
241 
GetCloudHspVersion(const std::string & hspPath,const std::string & actualName)242 std::string StageContext::GetCloudHspVersion(const std::string& hspPath, const std::string& actualName)
243 {
244     std::string flag = "@";
245     std::string spliter = actualName + flag;
246     // 以partName字符串拆分出版本号
247     size_t pos = hspPath.rfind(spliter);
248     if (pos == std::string::npos) {
249         ELOG("hspPath: %s format error. no spliter:%s exist", hspPath.c_str(), spliter.c_str());
250         return "";
251     }
252     int idx = pos + spliter.size();
253     return hspPath.substr(idx);
254 }
255 
SplitHspVersion(const std::string & version)256 std::vector<int> StageContext::SplitHspVersion(const std::string& version)
257 {
258     std::vector<int> segments;
259     std::istringstream iss(version);
260     std::string segment;
261     while (getline(iss, segment, '.')) {
262         segments.push_back(std::stoi(segment));
263     }
264     return segments;
265 }
266 
CompareHspVersion(const std::string & version1,const std::string & version2)267 int StageContext::CompareHspVersion(const std::string& version1, const std::string& version2)
268 {
269     ILOG("module hsp version:%s, project hsp version:%s", version1.c_str(), version2.c_str());
270     std::vector<int> ver1 = SplitHspVersion(version1);
271     std::vector<int> ver2 = SplitHspVersion(version2);
272     // 将两个版本号的分段个数补齐
273     while (ver1.size() < ver2.size()) {
274         ver1.push_back(0);
275     }
276     while (ver2.size() < ver1.size()) {
277         ver2.push_back(0);
278     }
279     // 逐段比较版本号
280     for (size_t i = 0; i < ver1.size(); ++i) {
281         if (ver1[i] < ver2[i]) {
282             return -1;
283         } else if (ver1[i] > ver2[i]) {
284             return 1;
285         }
286     }
287     return 0;
288 }
289 
GetActualCloudHspDir(const std::string & actualName)290 std::string StageContext::GetActualCloudHspDir(const std::string& actualName)
291 {
292     std::string moduleHspPath = GetCloudModuleHspPath(actualName);
293     std::string projectHspPath = GetCloudProjectHspPath(actualName);
294     ILOG("moduleHspPath:%s, projectHspPath:%s", moduleHspPath.c_str(), projectHspPath.c_str());
295     if (moduleHspPath.empty() || !FileSystem::IsDirectoryExists(moduleHspPath)) {
296         return projectHspPath; // 模块级不存在,加载项目级
297     }
298     if (projectHspPath.empty() || !FileSystem::IsDirectoryExists(projectHspPath)) {
299         return moduleHspPath; // 模块级存在,项目级不存在,加载模块级
300     }
301     // 模块级和项目级都存在,加载版本号高的
302     std::string moduleHspVersion = GetCloudHspVersion(moduleHspPath, actualName);
303     std::string projectHspVersion = GetCloudHspVersion(projectHspPath, actualName);
304     if (moduleHspVersion.empty()) {
305         return projectHspPath; // 模块级版本号不存在,加载项目级
306     }
307     if (projectHspVersion.empty()) {
308         return moduleHspPath; // 模块级版本号存在,项目级版本号不存在,加载模块级
309     }
310     int ret = CompareHspVersion(moduleHspVersion, projectHspVersion);
311     ILOG("CompareHspVersion result is:%d", ret);
312     return ret >= 0 ? moduleHspPath : projectHspPath; // 优先加载版本号高的,版本号相同则优先加载模块级的
313 }
314 
GetCloudProjectHspPath(const std::string & actualName)315 std::string StageContext::GetCloudProjectHspPath(const std::string& actualName)
316 {
317     ILOG("get projectRootPath:%s", projectRootPath.c_str());
318     std::string hspDir = projectRootPath + "/oh_modules/.hsp";
319     if (!FileSystem::IsDirectoryExists(hspDir)) {
320         ELOG("hspDir: %s in project is not exist.", hspDir.c_str());
321         return "";
322     }
323     return GetCloudHspPath(hspDir, actualName);
324 }
325 
GetCloudModuleHspPath(const std::string & actualName)326 std::string StageContext::GetCloudModuleHspPath(const std::string& actualName)
327 {
328     int upwardLevel = 5;
329     int pos = GetUpwardDirIndex(loaderJsonPath, upwardLevel);
330     if (pos < 0) {
331         ILOG("GetUpwardDirIndex:%d failed.", pos);
332         return "";
333     }
334     std::string moduleRootPath = loaderJsonPath.substr(0, pos);
335     ILOG("get moduleRootPath:%s", moduleRootPath.c_str());
336     std::string hspDir = moduleRootPath + "/oh_modules/.hsp";
337     if (!FileSystem::IsDirectoryExists(hspDir)) {
338         ELOG("hspDir: %s in module is not exist.", hspDir.c_str());
339         return "";
340     }
341     return GetCloudHspPath(hspDir, actualName);
342 }
343 
GetCloudModuleBuffer(const std::string & moduleName)344 std::vector<uint8_t>* StageContext::GetCloudModuleBuffer(const std::string& moduleName)
345 {
346     std::string actualName;
347     int ret = GetHspActualName(moduleName, actualName);
348     if (ret > 1) {
349         WLOG("have more same module name hsp in the project, load the first as default.");
350     }
351     if (actualName.empty()) {
352         ELOG("get hsp actual name failed.");
353         return nullptr;
354     }
355     // 1.以entry(指代模块根目录或项目根目录)拆分,拼接oh_modules/.hsp,在这个拼接目录下查找以actualName@开头的文件夹
356     // 2.获取拼接目录下的actualName.hsp文件
357     // 3.使用zlib获取hsp压缩包下的ets/modules.abc内容
358     std::string hspPath = GetActualCloudHspDir(actualName);
359     ILOG("get hspPath:%s actualName:%s", hspPath.c_str(), actualName.c_str());
360     if (!FileSystem::IsDirectoryExists(hspPath)) {
361         ELOG("hspPath: %s is not exist.", hspPath.c_str());
362         return nullptr;
363     }
364     std::string moduleHspFile = hspPath + "/" + actualName + ".hsp";
365     ILOG("get moduleHspFile:%s.", moduleHspFile.c_str());
366     if (!FileSystem::IsFileExists(moduleHspFile)) {
367         ELOG("the moduleHspFile:%s is not exist.", moduleHspFile.c_str());
368         return nullptr;
369     }
370     // unzip and get ets/moudles.abc buffer
371     std::vector<uint8_t>* buf = GetModuleBufferFromHsp(moduleHspFile, "ets/modules.abc");
372     if (!buf) {
373         ELOG("read modules.abc buffer failed.");
374     }
375     return buf;
376 }
377 
GetCloudHspPath(const std::string & hspDir,const std::string & moduleName)378 std::string StageContext::GetCloudHspPath(const std::string& hspDir, const std::string& moduleName)
379 {
380     std::string flag = "@";
381     std::string partName = moduleName + flag;
382     return FileSystem::FindSubfolderByName(hspDir, partName);
383 }
384 
GetModuleBufferFromHsp(const std::string & hspFilePath,const std::string & fileName)385 std::vector<uint8_t>* StageContext::GetModuleBufferFromHsp(const std::string& hspFilePath,
386     const std::string& fileName)
387 {
388     unzFile zipfile = unzOpen2(hspFilePath.c_str(), nullptr);
389     if (zipfile == NULL) {
390         ELOG("Failed to open the zip file: %s\n", hspFilePath.c_str());
391         return nullptr;
392     }
393 
394     if (unzLocateFile(zipfile, fileName.c_str(), 1) != UNZ_OK) {
395         ELOG("Failed to locate the file: %s\n", fileName.c_str());
396         unzClose(zipfile);
397         return nullptr;
398     }
399 
400     unz_file_info file_info;
401     if (unzGetCurrentFileInfo(zipfile, &file_info, NULL, 0, NULL, 0, NULL, 0) != UNZ_OK) {
402         ELOG("Failed to get the file info: %s\n", fileName.c_str());
403         unzClose(zipfile);
404         return nullptr;
405     }
406 
407     if (unzOpenCurrentFile(zipfile) != UNZ_OK) {
408         ELOG("Failed to open the file: %s\n", fileName.c_str());
409         unzClose(zipfile);
410         return nullptr;
411     }
412 
413     char buffer[1024];
414     int bytesRead;
415     std::vector<uint8_t>* fileContent = new(std::nothrow) std::vector<uint8_t>();
416     if (!fileContent) {
417         ELOG("Memory allocation failed: fileContent.");
418         return fileContent;
419     }
420     while ((bytesRead = unzReadCurrentFile(zipfile, buffer, sizeof(buffer))) > 0) {
421         fileContent->insert(fileContent->end(), buffer, buffer + bytesRead);
422     }
423     hspBufferPtrsVec.push_back(fileContent);
424     unzCloseCurrentFile(zipfile);
425     unzClose(zipfile);
426 
427     return fileContent;
428 }
429 
ContainsRelativePath(const std::string & path) const430 bool StageContext::ContainsRelativePath(const std::string& path) const
431 {
432     std::string flg1 = ".." + FileSystem::GetSeparator();
433     std::string flg2 = "." + FileSystem::GetSeparator();
434     return (path.find(flg1) != std::string::npos || path.find(flg2) != std::string::npos);
435 }
436 
ParseMockJsonFile(const std::string & mockJsonFilePath)437 std::map<std::string, std::string> StageContext::ParseMockJsonFile(const std::string& mockJsonFilePath)
438 {
439     std::map<std::string, std::string> mapInfo;
440     if (!FileSystem::IsFileExists(mockJsonFilePath)) {
441         ELOG("the mockJsonFilePath:%s is not exist.", mockJsonFilePath.c_str());
442         return mapInfo;
443     }
444     std::string jsonStr = JsonReader::ReadFile(mockJsonFilePath);
445     Json2::Value rootJson = JsonReader::ParseJsonData2(jsonStr);
446     if (rootJson.IsNull() || !rootJson.IsValid()) {
447         ELOG("get mock-config.json content failed.");
448         return mapInfo;
449     }
450     for (const auto& key : rootJson.GetMemberNames()) {
451         if (!rootJson[key].IsNull() && rootJson[key].IsMember("source") && rootJson[key]["source"].IsString()) {
452             mapInfo[key] = rootJson[key]["source"].AsString();
453         }
454     }
455     return mapInfo;
456 }
457 
GetUpwardDirIndex(const std::string & path,const int upwardLevel) const458 int StageContext::GetUpwardDirIndex(const std::string& path, const int upwardLevel) const
459 {
460     std::string::size_type pos = path.find_last_of(FileSystem::GetSeparator().c_str());
461     std::string::size_type count = 0;
462     while (count < upwardLevel) {
463         if (pos == std::string::npos) {
464             ELOG("GetUpwardDir:%s failed.");
465             int errCode = -1;
466             return errCode;
467         }
468         pos = path.find_last_of(FileSystem::GetSeparator().c_str(), pos - 1);
469         ++count;
470     }
471     ILOG("GetUpwardDir path:%s pos:%d", path.c_str(), pos);
472     return pos;
473 }
474 
ReplaceLastStr(const std::string & str,const std::string & find,const std::string & replace)475 std::string StageContext::ReplaceLastStr(const std::string& str, const std::string& find, const std::string& replace)
476 {
477     std::string ret = str;
478     size_t pos = ret.rfind(find);
479     if (pos != std::string::npos) {
480         ret.replace(pos, find.size(), replace);
481     }
482     return ret;
483 }
484 
GetHspActualName(const std::string & input,std::string & ret)485 int StageContext::GetHspActualName(const std::string& input, std::string& ret)
486 {
487     int num = 0;
488     std::string flag = "";
489     std::string bundleFlag = "/" + input + "/";
490     std::string normalizedFlag = "N&" + input + "&";
491     for (const auto& pair : hspNameOhmMap) {
492         if (pair.second.find("@normalized") == 0) {
493             flag = normalizedFlag;
494         } else {
495             flag = bundleFlag;
496         }
497         if (pair.second.find(flag) != std::string::npos) {
498             std::string actualName = pair.first;
499             if (actualName.find('/') != std::string::npos) { // 以组织名开头的包
500                 std::replace(actualName.begin(), actualName.end(), '/', '+');
501             }
502             if (num == 0) {
503                 ret = actualName;
504             }
505             num++;
506             WLOG("find hsp actual name:%s", actualName.c_str());
507         }
508     }
509     return num;
510 }
511 
GetSystemModuleBuffer(const std::string & inputPath,const std::string & moduleName)512 std::vector<uint8_t>* StageContext::GetSystemModuleBuffer(const std::string& inputPath,
513     const std::string& moduleName)
514 {
515     std::string head = "com.huawei";
516     std::string tail = moduleName;
517     size_t pos1 = inputPath.find(head) + head.size();
518     size_t pos2 = inputPath.find(tail);
519     std::string relativePath = inputPath.substr(pos1, pos2 - pos1);
520     size_t found = relativePath.find(".");
521     int len = 1;
522     while (found != std::string::npos) {
523         relativePath.replace(found, len, "/");
524         found = relativePath.find(".", found + len);
525     }
526     std::string moduleHspFile = hosSdkPath + "/systemHsp" + relativePath + moduleName + ".hsp";
527     ILOG("get system moduleHspFile:%s.", moduleHspFile.c_str());
528     if (!FileSystem::IsFileExists(moduleHspFile)) {
529         ELOG("the system moduleHspFile:%s is not exist.", moduleHspFile.c_str());
530         return nullptr;
531     }
532     // unzip and get ets/moudles.abc buffer
533     std::vector<uint8_t>* buf = GetModuleBufferFromHsp(moduleHspFile, "ets/modules.abc");
534     if (!buf) {
535         ELOG("read modules.abc buffer failed.");
536     }
537     return buf;
538 }
539 
SetPkgContextInfo(std::map<std::string,std::string> & pkgContextInfoJsonStringMap,std::map<std::string,std::string> & packageNameList)540 void StageContext::SetPkgContextInfo(std::map<std::string, std::string>& pkgContextInfoJsonStringMap,
541     std::map<std::string, std::string>& packageNameList)
542 {
543     const std::string path = CommandParser::GetInstance().GetAppResourcePath() +
544         FileSystem::GetSeparator() + "module.json";
545     std::string moduleJsonStr = JsonReader::ReadFile(path);
546     if (moduleJsonStr.empty()) {
547         ELOG("Get module.json content empty.");
548     }
549     Json2::Value rootJson1 = JsonReader::ParseJsonData2(moduleJsonStr);
550     if (rootJson1.IsNull() || !rootJson1.IsValid() || !rootJson1.IsMember("module")) {
551         ELOG("Get module.json content failed.");
552         return;
553     }
554     if (!rootJson1["module"].IsMember("name") || !rootJson1["module"]["name"].IsString()) {
555         return;
556     }
557     std::string moduleName = rootJson1["module"]["name"].AsString();
558     if (rootJson1["module"].IsMember("packageName") && rootJson1["module"]["packageName"].IsString()) {
559         std::string pkgName = rootJson1["module"]["packageName"].AsString();
560         packageNameList = {{moduleName, pkgName}};
561     }
562     std::string jsonPath = CommandParser::GetInstance().GetLoaderJsonPath();
563     std::string flag = "loader.json";
564     int idx = jsonPath.find_last_of(flag);
565     std::string dirPath = jsonPath.substr(0, idx - flag.size() + 1); // 1 is for \ or /
566     std::string ctxPath = dirPath + "pkgContextInfo.json";
567     std::string ctxInfoJsonStr = JsonReader::ReadFile(ctxPath);
568     if (ctxInfoJsonStr.empty()) {
569         ELOG("Get pkgContextInfo.json content empty.");
570         return;
571     }
572     pkgContextInfoJsonStringMap = {{moduleName, ctxInfoJsonStr}};
573     Json2::Value rootJson = JsonReader::ParseJsonData2(ctxInfoJsonStr);
574     if (rootJson.IsNull() || !rootJson.IsValid()) {
575         ELOG("parse ctx info json failed.");
576         return;
577     }
578     for (const auto& element : rootJson.GetMemberNames()) {
579         if (!rootJson[element]["moduleName"].IsString()) {
580             return;
581         }
582         packageNameMap[element] = rootJson[element]["moduleName"].AsString();
583     }
584 }
585 
UnzipHspFile(const std::string & hspFilePath,const std::string & writePath,const std::vector<std::string> fileNames)586 bool StageContext::UnzipHspFile(const std::string& hspFilePath, const std::string& writePath,
587     const std::vector<std::string> fileNames)
588 {
589     unzFile zipfile = unzOpen(hspFilePath.c_str());
590     if (zipfile == NULL) {
591         ELOG("Error: Unable to open zip file %s\n", hspFilePath.c_str());
592         return false;
593     }
594 
595     bool isUnzipSuccess = true;
596     for (const auto& fileName : fileNames) {
597         if (unzLocateFile(zipfile, fileName.c_str(), 1) != UNZ_OK) {
598             ELOG("Failed to locate the file: %s\n", fileName.c_str());
599             unzClose(zipfile);
600             return false;
601         }
602         unz_file_info file_info;
603         if (unzGetCurrentFileInfo(zipfile, &file_info, NULL, 0, NULL, 0, NULL, 0) != UNZ_OK) {
604             ELOG("Failed to get the file info: %s\n", fileName.c_str());
605             unzClose(zipfile);
606             return false;
607         }
608         if (unzOpenCurrentFile(zipfile) != UNZ_OK) {
609             ELOG("Failed to open the file: %s\n", fileName.c_str());
610             unzClose(zipfile);
611             return false;
612         }
613 
614         std::string filePath = writePath + FileSystem::GetSeparator() + fileName;
615         FILE *outputFile = fopen(filePath.c_str(), "wb");
616         if (outputFile == NULL) {
617             ELOG("Error: Unable to open output file %s\n", fileName.c_str());
618             unzCloseCurrentFile(zipfile);
619             break;
620         }
621 
622         char buffer[4096];
623         int bytesRead = 0;
624         do {
625             bytesRead = unzReadCurrentFile(zipfile, buffer, sizeof(buffer));
626             if (bytesRead < 0 || bytesRead != fwrite(buffer, 1, bytesRead, outputFile)) {
627                 ELOG("Failed to unzip all elements to the output file.\n");
628                 isUnzipSuccess = false;
629                 break;
630             }
631         } while (bytesRead > 0);
632 
633         fclose(outputFile);
634         unzCloseCurrentFile(zipfile);
635         if (!isUnzipSuccess) {
636             break;
637         }
638     }
639     unzClose(zipfile);
640     return isUnzipSuccess;
641 }
642 
GetModuleInfo(std::vector<HspInfo> & dependencyHspInfos)643 void StageContext::GetModuleInfo(std::vector<HspInfo>& dependencyHspInfos)
644 {
645     if (hspResourcesMap.empty()) {
646         ELOG("hspResourcesMap is empty.");
647         return;
648     }
649     for (const auto &pair : hspResourcesMap) {
650         std::string moduleName = pair.first;
651         std::string packageName = "";
652         HspInfo hspInfo;
653         int ret = GetHspActualName(moduleName, packageName);
654         if (ret > 1) {
655             WLOG("have more same module name hsp in the project, load the first as default.");
656         }
657         if (packageName.empty()) {
658             ELOG("get hsp actual name failed.");
659             return;
660         }
661         hspInfo.moduleName = moduleName;
662         GetHspinfo(packageName, hspInfo);
663         dependencyHspInfos.push_back(hspInfo);
664     }
665 }
666 
GetHspinfo(const std::string & packageName,HspInfo & hspInfo)667 void StageContext::GetHspinfo(const std::string& packageName, HspInfo& hspInfo)
668 {
669     if (modulePathMap.count(hspInfo.moduleName) > 0) {
670         bool ret = GetLocalModuleInfo(hspInfo);
671         if (!ret) {
672             GetCloudModuleInfo(packageName, hspInfo);
673         }
674     } else {
675         GetCloudModuleInfo(packageName, hspInfo);
676     }
677 }
678 
GetLocalModuleInfo(HspInfo & hspInfo)679 bool StageContext::GetLocalModuleInfo(HspInfo& hspInfo)
680 {
681     if (hspResourcesMap.find(hspInfo.moduleName) == hspResourcesMap.end()) {
682         ELOG("ResourcesPath is empty.");
683         return false;
684     }
685     std::string modulePath = hspResourcesMap[hspInfo.moduleName];
686     if (modulePath.empty()) {
687         ELOG("modulePath is empty.");
688         return false;
689     }
690     if (ContainsRelativePath(modulePath)) {
691         ELOG("modulePath format error: %s.", modulePath.c_str());
692         return false;
693     }
694     // 读取hsp的module.json和resources.index
695     std::string flag = "ResourceTable.txt";
696     int idx = modulePath.find_last_of(flag);
697     std::string dirPath = modulePath.substr(0, idx - flag.size() + 1); // 1 is for \ or /
698     std::string moduleJsonPath = dirPath + "module.json";
699     std::string resources = dirPath + "resources.index";
700     if (!FileSystem::IsFileExists(resources)) {
701         ELOG("The resources.index file is not exist.");
702         return false;
703     }
704     hspInfo.resourcePath = resources;
705     if (!FileSystem::IsFileExists(moduleJsonPath)) {
706         ELOG("The module.json file is not exist.");
707         return false;
708     }
709     std::optional<std::vector<uint8_t>> ctx = OHOS::Ide::StageContext::GetInstance().ReadFileContents(moduleJsonPath);
710     if (ctx.has_value()) {
711         hspInfo.moduleJsonBuffer = ctx.value();
712     } else {
713         ELOG("get %s module.json content failed", hspInfo.moduleName.c_str());
714     }
715     return true;
716 }
717 
GetCloudModuleInfo(const std::string & packageName,HspInfo & hspInfo)718 bool StageContext::GetCloudModuleInfo(const std::string& packageName, HspInfo& hspInfo)
719 {
720     std::string hspPath = GetActualCloudHspDir(packageName);
721     ILOG("get hspPath:%s actualName:%s", hspPath.c_str(), packageName.c_str());
722     if (!FileSystem::IsDirectoryExists(hspPath)) {
723         ELOG("hspPath: %s is not exist.", hspPath.c_str());
724         return false;
725     }
726     std::string moduleHspFile = hspPath + "/" + packageName + ".hsp";
727     ILOG("get moduleHspFile:%s.", moduleHspFile.c_str());
728     if (!FileSystem::IsFileExists(moduleHspFile)) {
729         ELOG("the moduleHspFile:%s is not exist.", moduleHspFile.c_str());
730         return false;
731     }
732     std::string separator = FileSystem::GetSeparator();
733     // 读取hsp的module.json和resources.index
734     std::vector<std::string> fileNames = {"module.json", "resources.index"};
735     if (!UnzipHspFile(moduleHspFile, hspPath, fileNames)) {
736         ELOG("unzip hsp file failed.");
737         return false;
738     };
739     std::string modulePath = hspPath + separator + "module.json";
740     std::string resources = hspPath + separator + "resources.index";
741     if (!FileSystem::IsFileExists(resources)) {
742         ELOG("The resources.index file is not exist.");
743         return false;
744     }
745     hspInfo.resourcePath = resources;
746     if (!FileSystem::IsFileExists(modulePath)) {
747         ELOG("The module.json file is not exist.");
748         return false;
749     }
750     std::optional<std::vector<uint8_t>> ctx = OHOS::Ide::StageContext::GetInstance().ReadFileContents(modulePath);
751     if (ctx.has_value()) {
752         hspInfo.moduleJsonBuffer = ctx.value();
753     } else {
754         ELOG("get %s module.json content failed", packageName.c_str());
755     }
756     return true;
757 }
758 }