• 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: " << 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 }