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("ConfigReader::ParseProperties name null!");
47 continue;
48 }
49 value = xmlGetProp(&currNode, name);
50 if (!value) {
51 RESSCHED_LOGW("ConfigReader::ParseProperties name(%{public}s) value null!", 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("ConfigReader::ParseSubItem skip invalid node!");
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("ConfigReader::ParseConfig propName null!");
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("ConfigReader::ParsePluginConfig propName null!");
122 return false;
123 }
124 string pluginName(reinterpret_cast<char*>(propName));
125 xmlFree(propName);
126 ParseConfig(currNode, pluginConfigs[pluginName]);
127 return true;
128 }
129
LoadFromCustConfigFile(const string & configFile)130 bool ConfigReader::LoadFromCustConfigFile(const string& configFile)
131 {
132 // skip the empty string, else you will get empty node
133 xmlDocPtr xmlDocPtr = xmlReadFile(configFile.c_str(), nullptr, XML_PARSE_NOBLANKS);
134 if (!xmlDocPtr) {
135 RESSCHED_LOGE("ConfigReader::LoadFromCustConfigFile xmlReadFile error!");
136 return false;
137 }
138 xmlNodePtr rootNodePtr = xmlDocGetRootElement(xmlDocPtr);
139 if (!rootNodePtr || !rootNodePtr->name ||
140 xmlStrcmp(rootNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_RES_SCHED)) != 0) {
141 RESSCHED_LOGE("ConfigReader::LoadFromCustConfigFile root element tag wrong!");
142 xmlFreeDoc(xmlDocPtr);
143 return false;
144 }
145 map<string, PluginConfigMap> allPluginConfigs;
146 xmlNodePtr currNodePtr = rootNodePtr->xmlChildrenNode;
147 for (; currNodePtr; currNodePtr = currNodePtr->next) {
148 if (IsInvalidNode(*currNodePtr)) {
149 continue;
150 }
151 bool ret = false;
152 if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_PLUGIN)) == 0) {
153 ret = ParsePluginConfig(*currNodePtr, allPluginConfigs);
154 }
155 if (!ret) {
156 RESSCHED_LOGW("ConfigReader::LoadFromCustConfigFile plugin (%{public}s) config wrong!", currNodePtr->name);
157 xmlFreeDoc(xmlDocPtr);
158 return false;
159 }
160 }
161 xmlFreeDoc(xmlDocPtr);
162 lock_guard<mutex> autoLock(configMutex_);
163 allPluginConfigs_ = std::move(allPluginConfigs);
164 return true;
165 }
166
GetConfig(const std::string & pluginName,const std::string & configName)167 PluginConfig ConfigReader::GetConfig(const std::string& pluginName, const std::string& configName)
168 {
169 lock_guard<mutex> autoLock(configMutex_);
170 PluginConfig config;
171 auto itMap = allPluginConfigs_.find(pluginName);
172 if (itMap == allPluginConfigs_.end()) {
173 RESSCHED_LOGE("ConfigReader::GetConfig no pluginName:%{public}s config!", pluginName.c_str());
174 return config;
175 }
176 PluginConfigMap configMap = allPluginConfigs_[pluginName];
177 auto itConfig = configMap.find(configName);
178 if (itConfig == configMap.end()) {
179 RESSCHED_LOGE("ConfigReader::GetConfig pluginName:%{public}s config:%{public}s null!",
180 pluginName.c_str(), configName.c_str());
181 return config;
182 }
183 return configMap[configName];
184 }
185 } // namespace ResourceSchedule
186 } // namespace OHOS