• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }