1 /*
2 * Copyright (c) 2022 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 "config_reader.h"
17 #include "res_sched_log.h"
18
19 using namespace std;
20
21 namespace OHOS {
22 namespace ResourceSchedule {
23 namespace {
24 constexpr auto XML_TAG_RES_SCHED = "ressched";
25 constexpr auto XML_TAG_PLUGIN = "plugin";
26 constexpr auto XML_TAG_CONFIG = "config";
27 constexpr auto XML_TAG_ITEM = "item";
28 constexpr auto XML_ATTR_NAME = "name";
29 }
30
IsInvalidNode(const xmlNode & currNode)31 bool ConfigReader::IsInvalidNode(const xmlNode& currNode)
32 {
33 if (!currNode.name || currNode.type == XML_COMMENT_NODE) {
34 return true;
35 }
36 return false;
37 }
38
ParseProperties(const xmlNode & currNode,map<string,string> & properties)39 void ConfigReader::ParseProperties(const xmlNode& currNode, map<string, string>& properties)
40 {
41 auto attrs = currNode.properties;
42 xmlChar *value;
43 for (; attrs; attrs = attrs->next) {
44 auto name = attrs->name;
45 if (!name) {
46 RESSCHED_LOGW("%{public}s, name null!", __func__);
47 continue;
48 }
49 value = xmlGetProp(&currNode, name);
50 if (!value) {
51 RESSCHED_LOGW("%{public}s, name(%{public}s) value null!", __func__, name);
52 continue;
53 }
54 properties[reinterpret_cast<const char*>(name)] = reinterpret_cast<const char*>(value);
55 xmlFree(value);
56 }
57 }
58
ParseSubItem(const xmlNode & parentNode,Item & item)59 void ConfigReader::ParseSubItem(const xmlNode& parentNode, Item& item)
60 {
61 auto currNodePtr = parentNode.xmlChildrenNode;
62 xmlChar *value;
63 for (; currNodePtr; currNodePtr = currNodePtr->next) {
64 if (IsInvalidNode(*currNodePtr)) {
65 RESSCHED_LOGW("%{public}s, skip invalid node!", __func__);
66 continue;
67 }
68 SubItem subItem;
69 ParseProperties(*currNodePtr, subItem.properties);
70 subItem.name = reinterpret_cast<const char*>(currNodePtr->name);
71 value = xmlNodeGetContent(currNodePtr);
72 if (value) {
73 string itemValue(reinterpret_cast<const char*>(value));
74 subItem.value = std::move(itemValue);
75 xmlFree(value);
76 }
77 item.subItemList.emplace_back(subItem);
78 }
79 }
80
ParseItem(const xmlNode & parentNode,PluginConfig & pluginConfig)81 void ConfigReader::ParseItem(const xmlNode& parentNode, PluginConfig& pluginConfig)
82 {
83 auto currNodePtr = parentNode.xmlChildrenNode;
84 for (; currNodePtr; currNodePtr = currNodePtr->next) {
85 if (IsInvalidNode(*currNodePtr) ||
86 xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_ITEM)) != 0) {
87 continue;
88 }
89 Item item;
90 ParseProperties(*currNodePtr, item.itemProperties);
91 ParseSubItem(*currNodePtr, item);
92 pluginConfig.itemList.emplace_back(item);
93 }
94 }
95
ParseConfig(const xmlNode & parentNode,PluginConfigMap & pluginConfigMap)96 void ConfigReader::ParseConfig(const xmlNode& parentNode, PluginConfigMap& pluginConfigMap)
97 {
98 auto currNodePtr = parentNode.xmlChildrenNode;
99 for (; currNodePtr; currNodePtr = currNodePtr->next) {
100 if (IsInvalidNode(*currNodePtr) ||
101 xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_CONFIG)) != 0) {
102 continue;
103 }
104 auto propName = xmlGetProp(currNodePtr, reinterpret_cast<const xmlChar*>(XML_ATTR_NAME));
105 if (!propName) {
106 RESSCHED_LOGW("%{public}s, propName null!", __func__);
107 continue;
108 }
109
110 string configName(reinterpret_cast<char*>(propName));
111 xmlFree(propName);
112 auto& pluginConfig = pluginConfigMap[configName];
113 ParseItem(*currNodePtr, pluginConfig);
114 }
115 }
116
ParsePluginConfig(const xmlNode & currNode,map<string,PluginConfigMap> & pluginConfigs)117 bool ConfigReader::ParsePluginConfig(const xmlNode& currNode, map<string, PluginConfigMap>& pluginConfigs)
118 {
119 auto propName = xmlGetProp(&currNode, reinterpret_cast<const xmlChar*>(XML_ATTR_NAME));
120 if (!propName) {
121 RESSCHED_LOGW("%{public}s, propName null!", __func__);
122 return false;
123 }
124 string pluginName(reinterpret_cast<char*>(propName));
125 xmlFree(propName);
126 ParseConfig(currNode, pluginConfigs[pluginName]);
127 return true;
128 }
129
LoadFromConfigContent(const string & content)130 bool ConfigReader::LoadFromConfigContent(const string& content)
131 {
132 // skip the empty string, else you will get empty node
133 xmlDocPtr xmlDocPtr = xmlReadMemory(content.c_str(), content.length(), nullptr, nullptr,
134 XML_PARSE_NOBLANKS | XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
135 if (!xmlDocPtr) {
136 RESSCHED_LOGE("%{public}s, xmlReadFile error!", __func__);
137 return false;
138 }
139 xmlNodePtr rootNodePtr = xmlDocGetRootElement(xmlDocPtr);
140 if (!rootNodePtr || !rootNodePtr->name ||
141 xmlStrcmp(rootNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_RES_SCHED)) != 0) {
142 RESSCHED_LOGE("%{public}s, root element tag wrong!", __func__);
143 xmlFreeDoc(xmlDocPtr);
144 return false;
145 }
146 map<string, PluginConfigMap> allPluginConfigs;
147 xmlNodePtr currNodePtr = rootNodePtr->xmlChildrenNode;
148 for (; currNodePtr; currNodePtr = currNodePtr->next) {
149 if (IsInvalidNode(*currNodePtr)) {
150 continue;
151 }
152 bool ret = false;
153 if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_PLUGIN)) == 0) {
154 ret = ParsePluginConfig(*currNodePtr, allPluginConfigs);
155 }
156 if (!ret) {
157 RESSCHED_LOGW("%{public}s, plugin (%{public}s) config wrong!", __func__, currNodePtr->name);
158 xmlFreeDoc(xmlDocPtr);
159 return false;
160 }
161 }
162 xmlFreeDoc(xmlDocPtr);
163 lock_guard<mutex> autoLock(configMutex_);
164 MergeConfigList(allPluginConfigs);
165 return true;
166 }
167
MergeConfigList(std::map<std::string,PluginConfigMap> & pluginConfigs)168 void ConfigReader::MergeConfigList(std::map<std::string, PluginConfigMap>& pluginConfigs)
169 {
170 for (auto iter : pluginConfigs) {
171 if (allPluginConfigs_.find(iter.first) == allPluginConfigs_.end()) {
172 allPluginConfigs_[iter.first] = iter.second;
173 continue;
174 }
175 MergePluginConfigMap(allPluginConfigs_[iter.first], iter.second);
176 }
177 }
178
MergePluginConfigMap(PluginConfigMap & curPluginConfigMap,const PluginConfigMap & nextPluginConfigMap)179 void ConfigReader::MergePluginConfigMap(PluginConfigMap& curPluginConfigMap,
180 const PluginConfigMap& nextPluginConfigMap)
181 {
182 for (auto iter : nextPluginConfigMap) {
183 curPluginConfigMap[iter.first] = iter.second;
184 }
185 }
186
GetConfig(const std::string & pluginName,const std::string & configName)187 PluginConfig ConfigReader::GetConfig(const std::string& pluginName, const std::string& configName)
188 {
189 lock_guard<mutex> autoLock(configMutex_);
190 PluginConfig config;
191 auto itMap = allPluginConfigs_.find(pluginName);
192 if (itMap == allPluginConfigs_.end()) {
193 RESSCHED_LOGE("%{public}s, no pluginName:%{public}s config!", __func__, pluginName.c_str());
194 return config;
195 }
196 PluginConfigMap configMap = allPluginConfigs_[pluginName];
197 auto itConfig = configMap.find(configName);
198 if (itConfig == configMap.end()) {
199 RESSCHED_LOGE("%{public}s, pluginName:%{public}s config:%{public}s null!", __func__,
200 pluginName.c_str(), configName.c_str());
201 return config;
202 }
203 return configMap[configName];
204 }
205
Dump(std::string & result)206 void ConfigReader::Dump(std::string &result)
207 {
208 result.append("================Resource Schedule Plugin Config ================\n");
209 for (auto pluginIter : allPluginConfigs_) {
210 result.append("pluginName:").append(pluginIter.first).append(" \n");
211 auto pluginConfigMap = pluginIter.second;
212 for (auto pluginConfigMapIter : pluginConfigMap) {
213 result.append("configName:").append(pluginConfigMapIter.first).append(" \n");
214 auto pluginConfig = pluginConfigMapIter.second;
215 for (auto item : pluginConfig.itemList) {
216 DumpItem(item, result);
217 }
218 }
219 }
220 }
221
DumpItem(const Item & item,std::string & result)222 void ConfigReader::DumpItem(const Item& item, std::string &result)
223 {
224 result.append("Item : ");
225 for (auto itemProPerty : item.itemProperties) {
226 result.append(itemProPerty.first).append(" = ").append(itemProPerty.second).append(" ");
227 }
228 result.append(" \n");
229 for (auto subItem : item.subItemList) {
230 result.append("subItemName : ").append(subItem.name).append(" ");
231 for (auto subItemProPerty : subItem.properties) {
232 result.append(subItemProPerty.first).append(" = ").append(subItemProPerty.second).append(" ");
233 }
234 result.append(" value :").append(subItem.value).append(" \n");
235 }
236 }
237 } // namespace ResourceSchedule
238 } // namespace OHOS
239