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 #include "increment_manager.h"
17 #include<algorithm>
18 #include<iostream>
19 #include "file_entry.h"
20 #include "id_worker.h"
21 #include "key_parser.h"
22 #include "module_combine.h"
23 #include "resource_module_inc.h"
24 #include "restool_errors.h"
25 #include "xml_key_node.h"
26
27 namespace OHOS {
28 namespace Global {
29 namespace Restool {
30 using namespace std;
31 const string IncrementManager::ID_JSON_FILE = "ids.json";
~IncrementManager()32 IncrementManager::~IncrementManager()
33 {
34 }
35
Init(const string & cachePath,const vector<std::string> & folder,const string & outputPath,const string & moduleName)36 uint32_t IncrementManager::Init(const string &cachePath, const vector<std::string> &folder,
37 const string &outputPath, const string &moduleName)
38 {
39 cachePath_ = cachePath;
40 folder_ = folder;
41 outputPath_ = outputPath;
42 moduleName_ = moduleName;
43
44 if (!InitIdJson()) {
45 return RESTOOL_ERROR;
46 }
47
48 if (!ClearSolidXml()) {
49 return RESTOOL_ERROR;
50 }
51
52 vector<IncrementList::FileIncrement> dels;
53 if (!InitList(dels)) {
54 return RESTOOL_ERROR;
55 }
56
57 DeleteRawFile(dels);
58 if (!ScanModules(dels)) {
59 return RESTOOL_ERROR;
60 }
61 enalbe_= true;
62 return RESTOOL_SUCCESS;
63 }
64
65 // below private
InitIdJson()66 bool IncrementManager::InitIdJson()
67 {
68 string idJsonPath = FileEntry::FilePath(cachePath_).Append(ID_JSON_FILE).GetPath();
69 if (!ResourceUtil::FileExist(idJsonPath)) {
70 return true;
71 }
72 if (!LoadIdJson()) {
73 return false;
74 }
75 firstIncrement_ = false;
76 return true;
77 }
78
ScanModules(const vector<IncrementList::FileIncrement> & dels)79 bool IncrementManager::ScanModules(const vector<IncrementList::FileIncrement> &dels)
80 {
81 vector<ModuleInfo> moduleInfos;
82 for (const auto &folder : folder_) {
83 ModuleInfo moduleInfo;
84 moduleInfo.rootPath = folder;
85 for_each(dels.begin(), dels.end(), [&moduleInfo](const auto &iter) {
86 if (moduleInfo.rootPath != iter.rootPath) {
87 return;
88 }
89 moduleInfo.fileIncrements.push_back(iter);
90 });
91 moduleInfos.push_back(moduleInfo);
92 }
93
94 for (auto &iter : moduleInfos) {
95 string pathHash = ResourceUtil::GenerateHash(iter.rootPath);
96 string moduleCachePath = FileEntry::FilePath(cachePath_).Append(pathHash).GetPath();
97 ResourceModuleInc resourceModuleInc(iter.rootPath, moduleCachePath, moduleName_, folder_);
98 if (FirstIncrement()) {
99 if (resourceModuleInc.ResourceModule::ScanResource() != RESTOOL_SUCCESS) {
100 return false;
101 }
102 } else {
103 if (resourceModuleInc.ScanResource(iter.fileIncrements) != RESTOOL_SUCCESS) {
104 return false;
105 }
106 }
107
108 PushScanDir(resourceModuleInc.GetScanDirectorys());
109 if (ResourceModule::MergeResourceItem(items_, resourceModuleInc.GetOwner()) != RESTOOL_SUCCESS) {
110 return false;
111 }
112 if (resourceModuleInc.SaveIndex() != RESTOOL_SUCCESS) {
113 return false;
114 }
115
116 ModuleCombine moduleCombine(moduleCachePath, outputPath_);
117 if (!moduleCombine.Combine()) {
118 return false;
119 }
120 }
121 FlushId();
122 SaveIdJson();
123 return true;
124 }
125
InitList(vector<IncrementList::FileIncrement> & dels) const126 bool IncrementManager::InitList(vector<IncrementList::FileIncrement> &dels) const
127 {
128 string listPath = FileEntry::FilePath(cachePath_).Append(IncrementList::RESTOOL_LIST_FILE).GetPath();
129 if (!ResourceUtil::FileExist(listPath)) {
130 return true;
131 }
132
133 IncrementList incrementList(listPath, folder_);
134 if (!incrementList.Parse(dels)) {
135 return false;
136 }
137 return true;
138 }
139
FlushId()140 void IncrementManager::FlushId()
141 {
142 for_each(items_.begin(), items_.end(), [](const auto &iter) {
143 auto &idWorker = IdWorker::GetInstance();
144 ResType resType = iter.second.begin()->GetResType();
145 string name = ResourceUtil::GetIdName(iter.second.begin()->GetName(), resType);
146 idWorker.GenerateId(resType, name);
147 });
148 }
149
SaveIdJson() const150 bool IncrementManager::SaveIdJson() const
151 {
152 Json::Value root;
153 for (const auto &iter : items_) {
154 Json::Value node;
155 ResType resType = iter.second.begin()->GetResType();
156 node["name"] = ResourceUtil::GetIdName(iter.second.begin()->GetName(), resType);
157 node["type"] = ResourceUtil::ResTypeToString(resType);
158 root[to_string(iter.first)] = node;
159 }
160
161 string idJsonPath = FileEntry::FilePath(cachePath_).Append(ID_JSON_FILE).GetPath();
162 if (!ResourceUtil::SaveToJsonFile(idJsonPath, root)) {
163 return false;
164 }
165 return true;
166 }
167
LoadIdJson()168 bool IncrementManager::LoadIdJson()
169 {
170 Json::Value root;
171 string idJsonPath = FileEntry::FilePath(cachePath_).Append(ID_JSON_FILE).GetPath();
172 if (!ResourceUtil::OpenJsonFile(idJsonPath, root)) {
173 return false;
174 }
175
176 if (!root.isObject()) {
177 cerr << "Error: invalid, not object." << NEW_LINE_PATH << idJsonPath << endl;
178 return false;
179 }
180
181 auto &idWorker = IdWorker::GetInstance();
182 for (const auto &member : root.getMemberNames()) {
183 int32_t id = strtol(member.c_str(), nullptr, 10);
184 if (id < 0) {
185 cerr << "Error: invalid '" << member << "'." << NEW_LINE_PATH << idJsonPath << endl;
186 return false;
187 }
188
189 const auto &node = root[member];
190 if (!node.isObject()) {
191 cerr << "Error: '" << member << "' not object." << NEW_LINE_PATH << idJsonPath << endl;
192 return false;
193 }
194 if (!node["name"].isString()) {
195 cerr << "Error: '" << member << "' name not string." << NEW_LINE_PATH << idJsonPath << endl;
196 return false;
197 }
198 string name = node["name"].asString();
199
200 if (!node["type"].isString()) {
201 cerr << "Error: '" << member << "' type not string." << NEW_LINE_PATH << idJsonPath << endl;
202 return false;
203 }
204 ResType resType = ResourceUtil::GetResTypeFromString(node["type"].asString());
205 if (resType == ResType::INVALID_RES_TYPE) {
206 cerr << "Error: '" << member << "' '" << node["type"] << "' invalid.";
207 cerr << NEW_LINE_PATH << idJsonPath << endl;
208 return false;
209 }
210 if (!idWorker.PushCache(resType, name, id)) {
211 return false;
212 }
213 }
214 return true;
215 }
216
PushScanDir(const map<ResType,vector<DirectoryInfo>> & scanDirs)217 void IncrementManager::PushScanDir(const map<ResType, vector<DirectoryInfo>> &scanDirs)
218 {
219 for (const auto &iter : scanDirs) {
220 for (const auto &directoryInfo : iter.second) {
221 scanDirs_[iter.first].push_back(directoryInfo);
222 }
223 }
224 }
225
DeleteRawFile(vector<IncrementList::FileIncrement> & dels) const226 void IncrementManager::DeleteRawFile(vector<IncrementList::FileIncrement> &dels) const
227 {
228 for (auto it = dels.begin(); it != dels.end();) {
229 if (it->dirType != ResType::INVALID_RES_TYPE) {
230 it++;
231 continue;
232 }
233 string rawFilePath = FileEntry::FilePath(outputPath_).Append(it->relativePath).GetPath();
234 if (remove(rawFilePath.c_str()) != 0) {
235 cout << "Warning: remove fail '" << rawFilePath << "'" << endl;
236 }
237 it = dels.erase(it);
238 }
239 }
240
ClearSolidXml() const241 bool IncrementManager::ClearSolidXml() const
242 {
243 string resourceDir = FileEntry::FilePath(outputPath_).Append(RESOURCES_DIR).GetPath();
244 if (!ResourceUtil::FileExist(resourceDir)) {
245 return true;
246 }
247
248 ResourceDirectory resourceDirectory;
249 if (!resourceDirectory.ScanResources(resourceDir, [](const DirectoryInfo &info) {
250 if (!ResourceUtil::NeedConverToSolidXml(info.dirType)) {
251 return true;
252 }
253
254 FileEntry f(info.dirPath);
255 if (!f.Init()) {
256 return false;
257 }
258
259 for (const auto &entry : f.GetChilds()) {
260 if (!entry->IsFile()) {
261 cerr << "Error: '" << entry->GetFilePath().GetPath() << "' is directroy." << endl;
262 return false;
263 }
264
265 string extension = entry->GetFilePath().GetExtension();
266 if (extension != ".sxml" && extension != ".key" && extension != ".json") {
267 continue;
268 }
269
270 if (remove(entry->GetFilePath().GetPath().c_str()) != 0) {
271 cerr << "Error: remove failed '" << entry->GetFilePath().GetPath();
272 cerr << "', reason: " << strerror(errno) << endl;
273 return false;
274 }
275 }
276 return true;
277 })) {
278 return false;
279 }
280 return true;
281 }
282 }
283 }
284 }
285