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_index.h"
17 #include<algorithm>
18 #include<iostream>
19 #include "key_parser.h"
20
21 namespace OHOS {
22 namespace Global {
23 namespace Restool {
24 using namespace std;
25 const string IncrementIndex::INDEX_FILE = "index.json";
IncrementIndex(const string & indexPath,const vector<string> & folder)26 IncrementIndex::IncrementIndex(const string &indexPath, const vector<string> &folder)
27 : indexPath_(indexPath), folder_(folder)
28 {
29 }
30
Save(const map<int32_t,vector<ResourceItem>> & items) const31 bool IncrementIndex::Save(const map<int32_t, vector<ResourceItem>> &items) const
32 {
33 Json::Value root;
34 root["header"] = Json::Value(Json::ValueType::objectValue);
35 root["header"]["folder"] = Json::Value(Json::ValueType::arrayValue);
36 for (const auto &folder : folder_) {
37 root["header"]["folder"].append(folder);
38 }
39
40 root["index"] = Json::Value(Json::ValueType::objectValue);
41 for (const auto &item : items) {
42 string id = to_string(item.first);
43 root["index"][id] = Json::Value(Json::ValueType::objectValue);
44 for (const auto &resourceItem : item.second) {
45 root["index"][id][resourceItem.GetFilePath()] = Json::Value(Json::ValueType::objectValue);
46 auto &record = root["index"][id][resourceItem.GetFilePath()];
47 string data(reinterpret_cast<const char *>(resourceItem.GetData()), resourceItem.GetDataLength());
48 record["data"] = data;
49 record["name"] = resourceItem.GetName();
50 record["limitkey"] = resourceItem.GetLimitKey();
51 record["type"] = ResourceUtil::ResTypeToString(resourceItem.GetResType());
52 }
53 }
54
55 if (!ResourceUtil::SaveToJsonFile(indexPath_, root)) {
56 return false;
57 }
58 return true;
59 }
60
Load(map<int32_t,vector<ResourceItem>> & items) const61 bool IncrementIndex::Load(map<int32_t, vector<ResourceItem>> &items) const
62 {
63 Json::Value indexJson;
64 if (!ResourceUtil::OpenJsonFile(indexPath_, indexJson)) {
65 return false;
66 }
67
68 auto headerInfo = indexJson["header"];
69 if (headerInfo.empty() || !headerInfo.isObject()) {
70 cerr << "Error: header info." << NEW_LINE_PATH << indexPath_ << endl;
71 return true;
72 }
73 auto folderInfo = headerInfo["folder"];
74 if (folderInfo.empty() || !folderInfo.isArray()) {
75 cerr << "Error: folder info." << NEW_LINE_PATH << indexPath_ << endl;
76 return false;
77 }
78 if (folder_.size() != folderInfo.size()) {
79 cerr << "Error: add/delete dependency, don't support increment compile." << endl;
80 return false;
81 }
82
83 for (size_t i = 0; i < folder_.size(); i++) {
84 if (folder_[i] != folderInfo[static_cast<int>(i)].asString()) {
85 cerr << "Error: dependency change, don't support increment compile." << endl;
86 return true;
87 }
88 }
89
90 if (!LoadIndex(indexJson["index"], items)) {
91 return false;
92 }
93 return true;
94 }
95
SetSkipPaths(const vector<string> & skipPaths)96 void IncrementIndex::SetSkipPaths(const vector<string> &skipPaths)
97 {
98 skipPaths_ = skipPaths;
99 }
100
101 // below private
LoadIndex(const Json::Value & indexInfo,map<int32_t,vector<ResourceItem>> & items) const102 bool IncrementIndex::LoadIndex(const Json::Value &indexInfo, map<int32_t, vector<ResourceItem>> &items) const
103 {
104 if (indexInfo.empty() || !indexInfo.isObject()) {
105 cerr << "Error: index info." << NEW_LINE_PATH << indexPath_ << endl;
106 return false;
107 }
108
109 for (const auto &idMember : indexInfo.getMemberNames()) {
110 int32_t id = strtol(idMember.c_str(), nullptr, 10);
111 if (id < 0) {
112 cerr << "Error: '" << idMember << "' not integer string." << NEW_LINE_PATH << indexPath_ << endl;
113 return false;
114 }
115 if (items.count(id) != 0) {
116 cerr << "Error: '" << idMember << "' duplicated." << NEW_LINE_PATH << indexPath_ << endl;
117 return false;
118 }
119 if (!indexInfo[idMember].isObject()) {
120 cerr << "Error: '" << idMember << "' not object." << NEW_LINE_PATH << indexPath_ << endl;
121 return false;
122 }
123 for (const auto &pathMember : indexInfo[idMember].getMemberNames()) {
124 if (IsIgnore(pathMember)) {
125 continue;
126 }
127 auto item = indexInfo[idMember][pathMember];
128 if (!item.isObject()) {
129 cerr << "Error: [" << idMember << "][" << pathMember<<"] not object.";
130 cerr << NEW_LINE_PATH << indexPath_ << endl;
131 return false;
132 }
133 ResourceItem resourceItem;
134 if (!ParseResourceItem(item, pathMember, resourceItem)) {
135 cerr << "Error: [" << idMember << "][" << pathMember<<"]." << NEW_LINE_PATH << indexPath_ << endl;
136 return false;
137 }
138 if (!PushResourceItem(resourceItem, id, items)) {
139 return false;
140 }
141 }
142 }
143 return true;
144 }
145
ParseResourceItem(const Json::Value & item,const string & filePath,ResourceItem & resourceItem) const146 bool IncrementIndex::ParseResourceItem(const Json::Value &item, const string &filePath,
147 ResourceItem &resourceItem) const
148 {
149 string name;
150 string type;
151 string limitKey;
152 string data;
153 if (!GetResourceItemProp(item, "name", name) || !GetResourceItemProp(item, "type", type) ||
154 !GetResourceItemProp(item, "limitkey", limitKey) || !GetResourceItemProp(item, "data", data)) {
155 cerr << "Error: 'name' 'type' 'limitkey' 'data' invalid." << endl;
156 return false;
157 }
158 ResType resType = ResourceUtil::GetResTypeFromString(type);
159 if (resType == ResType::INVALID_RES_TYPE) {
160 cerr << "Error: invaid ResType '" << type << "'." << NEW_LINE_PATH << indexPath_ << endl;
161 return false;
162 }
163 vector<KeyParam> keyParams;
164 if (!KeyParser::Parse(limitKey, keyParams)) {
165 return false;
166 }
167 ResourceItem temp(name, keyParams, resType);
168 if (resType != ResType::ID && !temp.SetData(reinterpret_cast<const int8_t *>(data.c_str()), data.length())) {
169 cerr << "Error: resource set data fail." << endl;
170 return false;
171 }
172 temp.SetFilePath(filePath);
173 temp.SetLimitKey(limitKey);
174 resourceItem = temp;
175 return true;
176 }
177
GetResourceItemProp(const Json::Value & item,const string & key,string & value) const178 bool IncrementIndex::GetResourceItemProp(const Json::Value &item, const string &key, string &value) const
179 {
180 if (item[key].empty() || !item[key].isString()) {
181 return false;
182 }
183 value = item[key].asString();
184 return true;
185 }
186
PushResourceItem(const ResourceItem & resourceItem,int32_t id,map<int32_t,vector<ResourceItem>> & items) const187 bool IncrementIndex::PushResourceItem(const ResourceItem &resourceItem, int32_t id,
188 map<int32_t, vector<ResourceItem>> &items) const
189 {
190 if (items.find(id) == items.end()) {
191 items[id].push_back(resourceItem);
192 return true;
193 }
194
195 const auto &first = items[id].begin();
196 if (resourceItem.GetName() != first->GetName()) {
197 cerr << "Error: '" << resourceItem.GetName() << "', expect '" << first->GetName() << "'.";
198 cerr << NEW_LINE_PATH << indexPath_ <<endl;
199 return false;
200 }
201 if (resourceItem.GetResType() != first->GetResType()) {
202 cerr << "Error: '" << ResourceUtil::ResTypeToString(resourceItem.GetResType());
203 cerr << "', expect '" << ResourceUtil::ResTypeToString(first->GetResType()) << "'.";
204 cerr << NEW_LINE_PATH << indexPath_ << endl;
205 return false;
206 }
207 auto result = find_if(items[id].begin(), items[id].end(), [&resourceItem](const auto &iter) {
208 return resourceItem.GetLimitKey() == iter.GetLimitKey();
209 });
210 if (result != items[id].end()) {
211 cerr << "Error: '" << resourceItem.GetLimitKey() << "' conflict." << NEW_LINE_PATH << indexPath_ << endl;
212 return false;
213 }
214 items[id].push_back(resourceItem);
215 return true;
216 }
217
IsIgnore(const string & filePath) const218 bool IncrementIndex::IsIgnore(const string &filePath) const
219 {
220 if (skipPaths_.empty()) {
221 return false;
222 }
223
224 if (find(skipPaths_.begin(), skipPaths_.end(), filePath) != skipPaths_.end()) {
225 return true;
226 }
227 return false;
228 }
229 }
230 }
231 }