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: " << indexPath_ << " header info." << endl;
71 return true;
72 }
73 auto folderInfo = headerInfo["folder"];
74 if (folderInfo.empty() || !folderInfo.isArray()) {
75 cerr << "Error: " << indexPath_ << " folder info." << 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: " << indexPath_ << " index info." << 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: " << indexPath_ << " '" << idMember << "' not integer string." << endl;
113 return false;
114 }
115 if (items.count(id) != 0) {
116 cerr << "Error: " << indexPath_ << " '" << idMember << "' duplicated." << endl;
117 return false;
118 }
119 if (!indexInfo[idMember].isObject()) {
120 cerr << "Error: " << indexPath_ << " '" << idMember << "' not object." << 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: " << indexPath_ << " [" << idMember << "][" << pathMember<<"] not object." << endl;
130 return false;
131 }
132 ResourceItem resourceItem;
133 if (!ParseResourceItem(item, pathMember, resourceItem)) {
134 cerr << "Error: " << indexPath_ << " [" << idMember << "][" << pathMember<<"]." << endl;
135 return false;
136 }
137 if (!PushResourceItem(resourceItem, id, items)) {
138 return false;
139 }
140 }
141 }
142 return true;
143 }
144
ParseResourceItem(const Json::Value & item,const string & filePath,ResourceItem & resourceItem) const145 bool IncrementIndex::ParseResourceItem(const Json::Value &item, const string &filePath,
146 ResourceItem &resourceItem) const
147 {
148 string name;
149 string type;
150 string limitKey;
151 string data;
152 if (!GetResourceItemProp(item, "name", name) || !GetResourceItemProp(item, "type", type) ||
153 !GetResourceItemProp(item, "limitkey", limitKey) || !GetResourceItemProp(item, "data", data)) {
154 cerr << "Error: 'name' 'type' 'limitkey' 'data' invalid." << endl;
155 return false;
156 }
157 ResType resType = ResourceUtil::GetResTypeFromString(type);
158 if (resType == ResType::INVALID_RES_TYPE) {
159 cerr << "Error: " << indexPath_ << " invaid ResType '" << type << "'" << endl;
160 return false;
161 }
162 vector<KeyParam> keyParams;
163 if (!KeyParser::Parse(limitKey, keyParams)) {
164 return false;
165 }
166 ResourceItem temp(name, keyParams, resType);
167 if (resType != ResType::ID && !temp.SetData(reinterpret_cast<const int8_t *>(data.c_str()), data.length())) {
168 cerr << "Error: resource set data fail." << endl;
169 return false;
170 }
171 temp.SetFilePath(filePath);
172 temp.SetLimitKey(limitKey);
173 resourceItem = temp;
174 return true;
175 }
176
GetResourceItemProp(const Json::Value & item,const string & key,string & value) const177 bool IncrementIndex::GetResourceItemProp(const Json::Value &item, const string &key, string &value) const
178 {
179 if (item[key].empty() || !item[key].isString()) {
180 return false;
181 }
182 value = item[key].asString();
183 return true;
184 }
185
PushResourceItem(const ResourceItem & resourceItem,int32_t id,map<int32_t,vector<ResourceItem>> & items) const186 bool IncrementIndex::PushResourceItem(const ResourceItem &resourceItem, int32_t id,
187 map<int32_t, vector<ResourceItem>> &items) const
188 {
189 if (items.find(id) == items.end()) {
190 items[id].push_back(resourceItem);
191 return true;
192 }
193
194 const auto &first = items[id].begin();
195 if (resourceItem.GetName() != first->GetName()) {
196 cerr << "Error: " << indexPath_ << " '" << resourceItem.GetName();
197 cerr << "', expect '" << first->GetName() << "'"<< endl;
198 return false;
199 }
200 if (resourceItem.GetResType() != first->GetResType()) {
201 cerr << "Error: " << indexPath_ << " '" << ResourceUtil::ResTypeToString(resourceItem.GetResType());
202 cerr << "', expect '" << ResourceUtil::ResTypeToString(first->GetResType()) << "'"<< endl;
203 return false;
204 }
205 auto result = find_if(items[id].begin(), items[id].end(), [&resourceItem](const auto &iter) {
206 return resourceItem.GetLimitKey() == iter.GetLimitKey();
207 });
208 if (result != items[id].end()) {
209 cerr << "Error: " << indexPath_ << " '" << resourceItem.GetLimitKey() << "' conflict." << endl;
210 return false;
211 }
212 items[id].push_back(resourceItem);
213 return true;
214 }
215
IsIgnore(const string & filePath) const216 bool IncrementIndex::IsIgnore(const string &filePath) const
217 {
218 if (skipPaths_.empty()) {
219 return false;
220 }
221
222 if (find(skipPaths_.begin(), skipPaths_.end(), filePath) != skipPaths_.end()) {
223 return true;
224 }
225 return false;
226 }
227 }
228 }
229 }