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
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,
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 allPluginConfigs_ = std::move(allPluginConfigs);
165 return true;
166 }
167
GetConfig(const std::string & pluginName,const std::string & configName)168 PluginConfig ConfigReader::GetConfig(const std::string& pluginName, const std::string& configName)
169 {
170 lock_guard<mutex> autoLock(configMutex_);
171 PluginConfig config;
172 auto itMap = allPluginConfigs_.find(pluginName);
173 if (itMap == allPluginConfigs_.end()) {
174 RESSCHED_LOGE("%{public}s, no pluginName:%{public}s config!", __func__, pluginName.c_str());
175 return config;
176 }
177 PluginConfigMap configMap = allPluginConfigs_[pluginName];
178 auto itConfig = configMap.find(configName);
179 if (itConfig == configMap.end()) {
180 RESSCHED_LOGE("%{public}s, pluginName:%{public}s config:%{public}s null!", __func__,
181 pluginName.c_str(), configName.c_str());
182 return config;
183 }
184 return configMap[configName];
185 }
186 } // namespace ResourceSchedule
187 } // namespace OHOS
188