1 /*
2 * Copyright (c) 2025 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 #include <ani.h>
16 #include <unordered_map>
17
18 #include "app_log_wrapper.h"
19 #include "bundle_errors.h"
20 #include "business_error_ani.h"
21 #include "business_error_map.h"
22 #include "napi_constants.h"
23 #include "common_fun_ani.h"
24
25 namespace OHOS {
26 namespace AppExecFwk {
27 namespace {
28 constexpr const char* ERROR_MESSAGE_PLACEHOLDER = "$";
29 constexpr const char* BUSINESS_ERROR_CLASS = "L@ohos/base/BusinessError;";
30 } // namespace
31
ThrowError(ani_env * env,int32_t err,const std::string & msg)32 void BusinessErrorAni::ThrowError(ani_env *env, int32_t err, const std::string &msg)
33 {
34 if (env == nullptr) {
35 APP_LOGE("env is null");
36 return;
37 }
38 ani_object error = CreateError(env, err, msg);
39 ThrowError(env, error);
40 }
41
WrapError(ani_env * env,const std::string & msg)42 ani_object BusinessErrorAni::WrapError(ani_env *env, const std::string &msg)
43 {
44 if (env == nullptr) {
45 APP_LOGE("env is null");
46 return nullptr;
47 }
48 ani_class cls = nullptr;
49 ani_method method = nullptr;
50 ani_object obj = nullptr;
51
52 ani_string aniMsg = nullptr;
53 if (!CommonFunAni::StringToAniStr(env, msg, aniMsg)) {
54 APP_LOGE("StringToAniStr failed");
55 return nullptr;
56 }
57
58 ani_ref undefRef;
59 env->GetUndefined(&undefRef);
60
61 ani_status status = env->FindClass("Lescompat/Error;", &cls);
62 if (status != ANI_OK) {
63 APP_LOGE("FindClass err : %{public}d", status);
64 return nullptr;
65 }
66 status = env->Class_FindMethod(cls, "<ctor>", "Lstd/core/String;Lescompat/ErrorOptions;:V", &method);
67 if (status != ANI_OK) {
68 APP_LOGE("Class_FindMethod err : %{public}d", status);
69 return nullptr;
70 }
71 status = env->Object_New(cls, method, &obj, aniMsg, undefRef);
72 if (status != ANI_OK) {
73 APP_LOGE("Object_New err : %{public}d", status);
74 return nullptr;
75 }
76 return obj;
77 }
78
CreateError(ani_env * env,int32_t code,const std::string & msg)79 ani_object BusinessErrorAni::CreateError(ani_env *env, int32_t code, const std::string& msg)
80 {
81 if (env == nullptr) {
82 APP_LOGE("err is nullptr");
83 return nullptr;
84 }
85 ani_class cls = nullptr;
86 ani_method method = nullptr;
87 ani_object obj = nullptr;
88 ani_status status = env->FindClass(BUSINESS_ERROR_CLASS, &cls);
89 if (status != ANI_OK) {
90 APP_LOGE("FindClass err : %{public}d", status);
91 return nullptr;
92 }
93 status = env->Class_FindMethod(cls, "<ctor>", "DLescompat/Error;:V", &method);
94 if (status != ANI_OK) {
95 APP_LOGE("Class_FindMethod err : %{public}d", status);
96 return nullptr;
97 }
98 ani_object error = WrapError(env, msg);
99 if (error == nullptr) {
100 APP_LOGE("WrapError failed");
101 return nullptr;
102 }
103 ani_double dCode(code);
104 status = env->Object_New(cls, method, &obj, dCode, error);
105 if (status != ANI_OK) {
106 APP_LOGE("Object_New err : %{public}d", status);
107 return nullptr;
108 }
109 return obj;
110 }
111
ThrowCommonError(ani_env * env,int32_t err,const std::string & parameter,const std::string & type)112 void BusinessErrorAni::ThrowCommonError(ani_env *env, int32_t err,
113 const std::string ¶meter, const std::string &type)
114 {
115 if (env == nullptr) {
116 APP_LOGE("err is nullptr");
117 return;
118 }
119 ani_object error = CreateCommonError(env, err, parameter, type);
120 ThrowError(env, error);
121 }
122
ThrowInstallError(ani_env * env,int32_t err,int32_t innerCode,const std::string & parameter,const std::string & type)123 void BusinessErrorAni::ThrowInstallError(ani_env *env, int32_t err, int32_t innerCode,
124 const std::string ¶meter, const std::string &type)
125 {
126 if (env == nullptr) {
127 APP_LOGE("err is nullptr");
128 return;
129 }
130 ani_object error = CreateInstallError(env, err, innerCode, parameter, type);
131 ThrowError(env, error);
132 }
133
ThrowTooFewParametersError(ani_env * env,int32_t err)134 void BusinessErrorAni::ThrowTooFewParametersError(ani_env *env, int32_t err)
135 {
136 if (env == nullptr) {
137 APP_LOGE("err is nullptr");
138 return;
139 }
140 ThrowError(env, err, BusinessErrorNS::ERR_MSG_PARAM_NUMBER_ERROR);
141 }
142
CreateCommonError(ani_env * env,int32_t err,const std::string & functionName,const std::string & permissionName)143 ani_object BusinessErrorAni::CreateCommonError(
144 ani_env *env, int32_t err, const std::string &functionName, const std::string &permissionName)
145 {
146 if (env == nullptr) {
147 APP_LOGE("err is nullptr");
148 return nullptr;
149 }
150 std::string errMessage = BusinessErrorNS::ERR_MSG_BUSINESS_ERROR;
151 auto iter = errMessage.find(ERROR_MESSAGE_PLACEHOLDER);
152 if (iter != std::string::npos) {
153 errMessage = errMessage.replace(iter, 1, std::to_string(err));
154 }
155 std::unordered_map<int32_t, const char*> errMap;
156 BusinessErrorMap::GetErrMap(errMap);
157 if (errMap.find(err) != errMap.end()) {
158 errMessage += errMap[err];
159 }
160 iter = errMessage.find(ERROR_MESSAGE_PLACEHOLDER);
161 if (iter != std::string::npos) {
162 errMessage = errMessage.replace(iter, 1, functionName);
163 iter = errMessage.find(ERROR_MESSAGE_PLACEHOLDER);
164 if (iter != std::string::npos) {
165 errMessage = errMessage.replace(iter, 1, permissionName);
166 }
167 }
168 return CreateError(env, err, errMessage);
169 }
170
CreateInstallError(ani_env * env,int32_t err,int32_t innerCode,const std::string & functionName,const std::string & permissionName)171 ani_object BusinessErrorAni::CreateInstallError(ani_env *env, int32_t err, int32_t innerCode,
172 const std::string &functionName, const std::string &permissionName)
173 {
174 if (env == nullptr) {
175 APP_LOGE("err is nullptr");
176 return nullptr;
177 }
178 std::string errMessage = BusinessErrorNS::ERR_MSG_BUSINESS_ERROR;
179 auto iter = errMessage.find(ERROR_MESSAGE_PLACEHOLDER);
180 if (iter != std::string::npos) {
181 errMessage = errMessage.replace(iter, 1, std::to_string(err));
182 }
183 std::unordered_map<int32_t, const char*> errMap;
184 BusinessErrorMap::GetErrMap(errMap);
185 if (errMap.find(err) != errMap.end()) {
186 errMessage += errMap[err];
187 }
188 errMessage += "[" + std::to_string(innerCode) + "]";
189 iter = errMessage.find(ERROR_MESSAGE_PLACEHOLDER);
190 if (iter != std::string::npos) {
191 errMessage = errMessage.replace(iter, 1, functionName);
192 iter = errMessage.find(ERROR_MESSAGE_PLACEHOLDER);
193 if (iter != std::string::npos) {
194 errMessage = errMessage.replace(iter, 1, permissionName);
195 }
196 }
197 return CreateError(env, err, errMessage);
198 }
199
ThrowEnumError(ani_env * env,const std::string & parameter,const std::string & type)200 void BusinessErrorAni::ThrowEnumError(ani_env *env,
201 const std::string ¶meter, const std::string &type)
202 {
203 if (env == nullptr) {
204 APP_LOGE("err is nullptr");
205 return;
206 }
207 ani_object error = CreateEnumError(env, parameter, type);
208 ThrowError(env, error);
209 }
210
CreateEnumError(ani_env * env,const std::string & parameter,const std::string & enumClass)211 ani_object BusinessErrorAni::CreateEnumError(ani_env *env,
212 const std::string ¶meter, const std::string &enumClass)
213 {
214 if (env == nullptr) {
215 APP_LOGE("err is nullptr");
216 return nullptr;
217 }
218 std::string errMessage = BusinessErrorNS::ERR_MSG_BUSINESS_ERROR;
219 auto iter = errMessage.find(ERROR_MESSAGE_PLACEHOLDER);
220 if (iter != std::string::npos) {
221 errMessage = errMessage.replace(iter, 1, std::to_string(ERROR_PARAM_CHECK_ERROR));
222 }
223 errMessage += BusinessErrorNS::ERR_MSG_ENUM_ERROR;
224 iter = errMessage.find(ERROR_MESSAGE_PLACEHOLDER);
225 if (iter != std::string::npos) {
226 errMessage = errMessage.replace(iter, 1, parameter);
227 iter = errMessage.find(ERROR_MESSAGE_PLACEHOLDER);
228 if (iter != std::string::npos) {
229 errMessage = errMessage.replace(iter, 1, enumClass);
230 }
231 }
232 return CreateError(env, ERROR_PARAM_CHECK_ERROR, errMessage);
233 }
234
ThrowError(ani_env * env,ani_object err)235 void BusinessErrorAni::ThrowError(ani_env *env, ani_object err)
236 {
237 if (err == nullptr) {
238 APP_LOGE("err is nullptr");
239 return;
240 }
241 env->ThrowError(static_cast<ani_error>(err));
242 }
243 } // namespace AppExecFwk
244 } // namespace OHOS