1020a203aSopenharmony_ci/*
2020a203aSopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3020a203aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4020a203aSopenharmony_ci * you may not use this file except in compliance with the License.
5020a203aSopenharmony_ci * You may obtain a copy of the License at
6020a203aSopenharmony_ci *
7020a203aSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8020a203aSopenharmony_ci *
9020a203aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10020a203aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11020a203aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12020a203aSopenharmony_ci * See the License for the specific language governing permissions and
13020a203aSopenharmony_ci * limitations under the License.
14020a203aSopenharmony_ci */
15020a203aSopenharmony_ci
16020a203aSopenharmony_ci#include "event_json_parser.h"
17020a203aSopenharmony_ci
18020a203aSopenharmony_ci#include <cctype>
19020a203aSopenharmony_ci#include <cinttypes>
20020a203aSopenharmony_ci#include <fstream>
21020a203aSopenharmony_ci#include <map>
22020a203aSopenharmony_ci
23020a203aSopenharmony_ci#include "hiview_logger.h"
24020a203aSopenharmony_ci
25020a203aSopenharmony_cinamespace OHOS {
26020a203aSopenharmony_cinamespace HiviewDFX {
27020a203aSopenharmony_cinamespace {
28020a203aSopenharmony_ciDEFINE_LOG_TAG("Event-JsonParser");
29020a203aSopenharmony_ci
30020a203aSopenharmony_ciconstexpr char BASE[] = "__BASE";
31020a203aSopenharmony_ciconstexpr char LEVEL[] = "level";
32020a203aSopenharmony_ciconstexpr char TAG[] = "tag";
33020a203aSopenharmony_ciconstexpr char TYPE[] = "type";
34020a203aSopenharmony_ciconstexpr char PRIVACY[] = "privacy";
35020a203aSopenharmony_ciconstexpr char PRESERVE[] = "preserve";
36020a203aSopenharmony_ciconst std::map<std::string, uint8_t> EVENT_TYPE_MAP = {
37020a203aSopenharmony_ci    {"FAULT", 1}, {"STATISTIC", 2}, {"SECURITY", 3}, {"BEHAVIOR", 4}
38020a203aSopenharmony_ci};
39020a203aSopenharmony_ci
40020a203aSopenharmony_cibool ReadSysEventDefFromFile(const std::string& path, Json::Value& hiSysEventDef)
41020a203aSopenharmony_ci{
42020a203aSopenharmony_ci    std::ifstream fin(path, std::ifstream::binary);
43020a203aSopenharmony_ci    if (!fin.is_open()) {
44020a203aSopenharmony_ci        HIVIEW_LOGW("failed to open file, path: %{public}s.", path.c_str());
45020a203aSopenharmony_ci        return false;
46020a203aSopenharmony_ci    }
47020a203aSopenharmony_ci    Json::CharReaderBuilder jsonRBuilder;
48020a203aSopenharmony_ci    Json::CharReaderBuilder::strictMode(&jsonRBuilder.settings_);
49020a203aSopenharmony_ci    JSONCPP_STRING errs;
50020a203aSopenharmony_ci    return parseFromStream(jsonRBuilder, fin, &hiSysEventDef, &errs);
51020a203aSopenharmony_ci}
52020a203aSopenharmony_ci}
53020a203aSopenharmony_ci
54020a203aSopenharmony_ciEventJsonParser::EventJsonParser(const std::string& defFilePath)
55020a203aSopenharmony_ci{
56020a203aSopenharmony_ci    // read json file
57020a203aSopenharmony_ci    ReadDefFile(defFilePath);
58020a203aSopenharmony_ci}
59020a203aSopenharmony_ci
60020a203aSopenharmony_cistd::string EventJsonParser::GetTagByDomainAndName(const std::string& domain, const std::string& name) const
61020a203aSopenharmony_ci{
62020a203aSopenharmony_ci    return GetDefinedBaseInfoByDomainName(domain, name).tag;
63020a203aSopenharmony_ci}
64020a203aSopenharmony_ci
65020a203aSopenharmony_ciint EventJsonParser::GetTypeByDomainAndName(const std::string& domain, const std::string& name) const
66020a203aSopenharmony_ci{
67020a203aSopenharmony_ci    return GetDefinedBaseInfoByDomainName(domain, name).type;
68020a203aSopenharmony_ci}
69020a203aSopenharmony_ci
70020a203aSopenharmony_cibool EventJsonParser::GetPreserveByDomainAndName(const std::string& domain, const std::string& name) const
71020a203aSopenharmony_ci{
72020a203aSopenharmony_ci    return GetDefinedBaseInfoByDomainName(domain, name).preserve;
73020a203aSopenharmony_ci}
74020a203aSopenharmony_ci
75020a203aSopenharmony_ciBaseInfo EventJsonParser::GetDefinedBaseInfoByDomainName(const std::string& domain,
76020a203aSopenharmony_ci    const std::string& name) const
77020a203aSopenharmony_ci{
78020a203aSopenharmony_ci    if (hiSysEventDefMap_ == nullptr) {
79020a203aSopenharmony_ci        HIVIEW_LOGD("sys def map is null");
80020a203aSopenharmony_ci        return BaseInfo();
81020a203aSopenharmony_ci    }
82020a203aSopenharmony_ci    auto domainIter = hiSysEventDefMap_->find(domain);
83020a203aSopenharmony_ci    if (domainIter == hiSysEventDefMap_->end()) {
84020a203aSopenharmony_ci        HIVIEW_LOGD("domain %{public}s is not defined.", domain.c_str());
85020a203aSopenharmony_ci        return BaseInfo();
86020a203aSopenharmony_ci    }
87020a203aSopenharmony_ci    auto domainNames = hiSysEventDefMap_->at(domain);
88020a203aSopenharmony_ci    auto nameIter = domainNames.find(name);
89020a203aSopenharmony_ci    if (nameIter == domainNames.end()) {
90020a203aSopenharmony_ci        HIVIEW_LOGD("%{public}s is not defined in domain %{public}s.", name.c_str(), domain.c_str());
91020a203aSopenharmony_ci        return BaseInfo();
92020a203aSopenharmony_ci    }
93020a203aSopenharmony_ci    return nameIter->second;
94020a203aSopenharmony_ci}
95020a203aSopenharmony_ci
96020a203aSopenharmony_cibool EventJsonParser::HasIntMember(const Json::Value& jsonObj, const std::string& name) const
97020a203aSopenharmony_ci{
98020a203aSopenharmony_ci    return jsonObj.isMember(name.c_str()) && jsonObj[name.c_str()].isInt();
99020a203aSopenharmony_ci}
100020a203aSopenharmony_ci
101020a203aSopenharmony_cibool EventJsonParser::HasStringMember(const Json::Value& jsonObj, const std::string& name) const
102020a203aSopenharmony_ci{
103020a203aSopenharmony_ci    return jsonObj.isMember(name.c_str()) && jsonObj[name.c_str()].isString();
104020a203aSopenharmony_ci}
105020a203aSopenharmony_ci
106020a203aSopenharmony_cibool EventJsonParser::HasBoolMember(const Json::Value& jsonObj, const std::string& name) const
107020a203aSopenharmony_ci{
108020a203aSopenharmony_ci    return jsonObj.isMember(name.c_str()) && jsonObj[name.c_str()].isBool();
109020a203aSopenharmony_ci}
110020a203aSopenharmony_ci
111020a203aSopenharmony_civoid EventJsonParser::InitEventInfoMapRef(const Json::Value& eventJson, JSON_VALUE_LOOP_HANDLER handler) const
112020a203aSopenharmony_ci{
113020a203aSopenharmony_ci    if (!eventJson.isObject()) {
114020a203aSopenharmony_ci        return;
115020a203aSopenharmony_ci    }
116020a203aSopenharmony_ci    auto attrList = eventJson.getMemberNames();
117020a203aSopenharmony_ci    for (auto it = attrList.cbegin(); it != attrList.cend(); it++) {
118020a203aSopenharmony_ci        std::string key = *it;
119020a203aSopenharmony_ci        if (key.empty()) {
120020a203aSopenharmony_ci            continue;
121020a203aSopenharmony_ci        }
122020a203aSopenharmony_ci        if (handler != nullptr) {
123020a203aSopenharmony_ci            handler(key, eventJson[key]);
124020a203aSopenharmony_ci        }
125020a203aSopenharmony_ci    }
126020a203aSopenharmony_ci}
127020a203aSopenharmony_ci
128020a203aSopenharmony_ciBaseInfo EventJsonParser::ParseBaseConfig(const Json::Value& eventNameJson) const
129020a203aSopenharmony_ci{
130020a203aSopenharmony_ci    BaseInfo baseInfo;
131020a203aSopenharmony_ci    if (!eventNameJson.isObject() || !eventNameJson[BASE].isObject()) {
132020a203aSopenharmony_ci        HIVIEW_LOGD("__BASE definition is invalid.");
133020a203aSopenharmony_ci        return baseInfo;
134020a203aSopenharmony_ci    }
135020a203aSopenharmony_ci
136020a203aSopenharmony_ci    Json::Value baseJsonInfo = eventNameJson[BASE];
137020a203aSopenharmony_ci    if (!baseJsonInfo.isObject() || !HasStringMember(baseJsonInfo, TYPE)) {
138020a203aSopenharmony_ci        HIVIEW_LOGD("type is not defined in __BASE.");
139020a203aSopenharmony_ci        return baseInfo;
140020a203aSopenharmony_ci    }
141020a203aSopenharmony_ci    std::string typeDes = baseJsonInfo[TYPE].asString();
142020a203aSopenharmony_ci    if (EVENT_TYPE_MAP.find(typeDes) == EVENT_TYPE_MAP.end()) {
143020a203aSopenharmony_ci        HIVIEW_LOGD("type is defined as %{public}s, but a valid type must be FAULT, STATISTIC, SECURITY, or BEHAVIOR",
144020a203aSopenharmony_ci            typeDes.c_str());
145020a203aSopenharmony_ci        return baseInfo;
146020a203aSopenharmony_ci    }
147020a203aSopenharmony_ci    baseInfo.type = EVENT_TYPE_MAP.at(typeDes);
148020a203aSopenharmony_ci
149020a203aSopenharmony_ci    if (!HasStringMember(baseJsonInfo, LEVEL)) {
150020a203aSopenharmony_ci        HIVIEW_LOGD("level is not defined in __BASE.");
151020a203aSopenharmony_ci        return baseInfo;
152020a203aSopenharmony_ci    }
153020a203aSopenharmony_ci    baseInfo.level = baseJsonInfo[LEVEL].asString();
154020a203aSopenharmony_ci
155020a203aSopenharmony_ci    if (HasStringMember(baseJsonInfo, TAG)) {
156020a203aSopenharmony_ci        baseInfo.tag = baseJsonInfo[TAG].asString();
157020a203aSopenharmony_ci    }
158020a203aSopenharmony_ci
159020a203aSopenharmony_ci    if (HasIntMember(baseJsonInfo, PRIVACY)) {
160020a203aSopenharmony_ci        int privacy = baseJsonInfo[PRIVACY].asInt();
161020a203aSopenharmony_ci        baseInfo.privacy = privacy > 0 ? static_cast<uint8_t>(privacy) : baseInfo.privacy;
162020a203aSopenharmony_ci    }
163020a203aSopenharmony_ci
164020a203aSopenharmony_ci    if (HasBoolMember(baseJsonInfo, PRESERVE)) {
165020a203aSopenharmony_ci        baseInfo.preserve = baseJsonInfo[PRESERVE].asBool();
166020a203aSopenharmony_ci    }
167020a203aSopenharmony_ci
168020a203aSopenharmony_ci    return baseInfo;
169020a203aSopenharmony_ci}
170020a203aSopenharmony_ci
171020a203aSopenharmony_civoid EventJsonParser::ParseHiSysEventDef(const Json::Value& hiSysEventDef, std::shared_ptr<DOMAIN_INFO_MAP> sysDefMap)
172020a203aSopenharmony_ci{
173020a203aSopenharmony_ci    InitEventInfoMapRef(hiSysEventDef, [this, sysDefMap] (const std::string& key, const Json::Value& value) {
174020a203aSopenharmony_ci       sysDefMap->insert(std::make_pair(key, this->ParseNameConfig(value)));
175020a203aSopenharmony_ci    });
176020a203aSopenharmony_ci}
177020a203aSopenharmony_ci
178020a203aSopenharmony_ciNAME_INFO_MAP EventJsonParser::ParseNameConfig(const Json::Value& domainJson) const
179020a203aSopenharmony_ci{
180020a203aSopenharmony_ci    NAME_INFO_MAP allNames;
181020a203aSopenharmony_ci    if (!domainJson.isObject()) {
182020a203aSopenharmony_ci        return allNames;
183020a203aSopenharmony_ci    }
184020a203aSopenharmony_ci    InitEventInfoMapRef(domainJson, [this, &allNames] (const std::string& key, const Json::Value& value) {
185020a203aSopenharmony_ci        allNames[key] = ParseBaseConfig(value);
186020a203aSopenharmony_ci    });
187020a203aSopenharmony_ci    return allNames;
188020a203aSopenharmony_ci}
189020a203aSopenharmony_ci
190020a203aSopenharmony_civoid EventJsonParser::ReadDefFile(const std::string& defFilePath)
191020a203aSopenharmony_ci{
192020a203aSopenharmony_ci    Json::Value hiSysEventDef;
193020a203aSopenharmony_ci    if (!ReadSysEventDefFromFile(defFilePath, hiSysEventDef)) {
194020a203aSopenharmony_ci        HIVIEW_LOGE("parse json file failed, please check the style of json file: %{public}s", defFilePath.c_str());
195020a203aSopenharmony_ci        return;
196020a203aSopenharmony_ci    }
197020a203aSopenharmony_ci    auto tmpMap = std::make_shared<DOMAIN_INFO_MAP>();
198020a203aSopenharmony_ci    ParseHiSysEventDef(hiSysEventDef, tmpMap);
199020a203aSopenharmony_ci    hiSysEventDefMap_ = tmpMap;
200020a203aSopenharmony_ci}
201020a203aSopenharmony_ci} // namespace HiviewDFX
202020a203aSopenharmony_ci} // namespace OHOS
203