• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "ani_util_native_ptr.h"
17 #include "common_func.h"
18 #include "file_uri_entity.h"
19 #include "file_utils.h"
20 #include "log.h"
21 #include "n_error.h"
22 #include <ani.h>
23 #include <iostream>
24 #include <vector>
25 
26 using namespace OHOS::AppFileService;
27 
ParseObjToStr(ani_env * env,ani_string stringObj)28 static std::string ParseObjToStr(ani_env *env, ani_string stringObj)
29 {
30     ani_size strSize;
31     env->String_GetUTF8Size(stringObj, &strSize);
32     std::vector<char> buffer(strSize + 1);
33     char *utf8Buffer = buffer.data();
34 
35     ani_size byteswritten = 0;
36     env->String_GetUTF8(stringObj, utf8Buffer, strSize + 1, &byteswritten);
37 
38     utf8Buffer[byteswritten] = '\0';
39     std::string path = std::string(utf8Buffer);
40     return path;
41 }
42 
unwrapp(ani_env * env,ani_object object)43 static ModuleFileUri::FileUriEntity *unwrapp(ani_env *env, ani_object object)
44 {
45     ani_long fileUriEntityHolder_;
46     if (ANI_OK != env->Object_GetFieldByName_Long(object, "fileUriEntity_", &fileUriEntityHolder_)) {
47         LOGE("Get fileuriEntityHolder_ failed");
48         return nullptr;
49     }
50     auto fileUriHolder = reinterpret_cast<StdSharedPtrHolder<ModuleFileUri::FileUriEntity> *>(fileUriEntityHolder_);
51     if (!fileUriHolder) {
52         LOGE("Get fileuriEntityHolder by long ptr failed");
53         return nullptr;
54     }
55     return reinterpret_cast<ModuleFileUri::FileUriEntity *>(fileUriHolder->Get().get());
56 }
57 
ThrowBusinessError(ani_env * env,int errCode,std::string && errMsg)58 static void ThrowBusinessError(ani_env *env, int errCode, std::string &&errMsg)
59 {
60     LOGD("Begin ThrowBusinessError.");
61     static const char *errorClsName = "L@ohos/base/BusinessError;";
62     ani_class cls {};
63     if (ANI_OK != env->FindClass(errorClsName, &cls)) {
64         LOGE("find class BusinessError %{public}s failed", errorClsName);
65         return;
66     }
67     ani_method ctor;
68     if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", ":V", &ctor)) {
69         LOGE("find method BusinessError.constructor failed");
70         return;
71     }
72     ani_object errorObject;
73     if (ANI_OK != env->Object_New(cls, ctor, &errorObject)) {
74         LOGE("create BusinessError object failed");
75         return;
76     }
77     ani_string errMsgStr;
78     if (ANI_OK != env->String_NewUTF8(errMsg.c_str(), errMsg.size(), &errMsgStr)) {
79         LOGE("convert errMsg to ani_string failed");
80         return;
81     }
82     if (ANI_OK != env->Object_SetFieldByName_Double(errorObject, "code", static_cast<ani_double>(errCode))) {
83         LOGE("set error code failed");
84         return;
85     }
86     if (ANI_OK != env->Object_SetPropertyByName_Ref(errorObject, "message", errMsgStr)) {
87         LOGE("set error message failed");
88         return;
89     }
90     if (ANI_OK != env->ThrowError(static_cast<ani_error>(errorObject))) {
91         LOGE("throw error object failed");
92     }
93     return;
94 }
95 
GetUriFromPath(ani_env * env,ani_string stringObj)96 static ani_string GetUriFromPath(ani_env *env, ani_string stringObj)
97 {
98     LOGD("Enter GetUriFromPath");
99     ani_string uriObj = nullptr;
100     std::string path = ParseObjToStr(env, stringObj);
101 
102     std::string uri = CommonFunc::GetUriFromPath(path);
103     if (uri == "") {
104         LOGE("CommonFunc::GetUriFromPath failed!");
105         ThrowBusinessError(env, OHOS::FileManagement::LibN::E_PARAMS, "CommonFunc::GetUriFromPath failed!");
106         return uriObj;
107     }
108     LOGD("GetUriFromPath uri: %{public}s", uri.c_str());
109 
110     ani_status status = env->String_NewUTF8(uri.c_str(), uri.size(), &uriObj);
111     if (status != ANI_OK) {
112         LOGE("String_NewUTF8 failed with status: %{public}d", status);
113         return nullptr;
114     }
115 
116     return uriObj;
117 }
118 
FileUriConstructor(ani_env * env,ani_object obj,ani_string stringObj)119 static void FileUriConstructor(ani_env *env, ani_object obj, ani_string stringObj)
120 {
121     LOGD("Enter FileUriConstructor");
122     std::string path = ParseObjToStr(env, stringObj);
123     if (path == "") {
124         LOGE("FileUriConstructor get path parameter failed!");
125         ThrowBusinessError(env, EINVAL, "Failed to get path");
126         return;
127     }
128     auto fileuriEntity = OHOS::FileManagement::CreateUniquePtr<ModuleFileUri::FileUriEntity>(path);
129     if (fileuriEntity == nullptr) {
130         LOGE("Failed to request heap memory.");
131         ThrowBusinessError(env, ENOMEM, "Failed to request heap memory.");
132         return;
133     }
134     StdSharedPtrHolder<ModuleFileUri::FileUriEntity> *holder =
135         new StdSharedPtrHolder<ModuleFileUri::FileUriEntity>(std::move(fileuriEntity));
136     if (holder == nullptr) {
137         return;
138     }
139 
140     ani_namespace ns;
141     if (env->FindNamespace("L@ohos/file/fileuri/fileUri;", &ns) != ANI_OK) {
142         LOGE("Namespace L@ohos/file/fileuri/fileUri not found.");
143         delete holder;
144         ThrowBusinessError(env, EPERM, "Namespace L@ohos/file/fileuri/fileUri not found.");
145         return;
146     };
147 
148     ani_class cls;
149     static const char *className = "LFileUri;";
150     if (env->Namespace_FindClass(ns, className, &cls) != ANI_OK) {
151         LOGE("Not found class LFileUri in Namespace L@ohos/file/fileuri/fileUri.");
152         delete holder;
153         ThrowBusinessError(env, EPERM, "Class LFileUri not found.");
154         return;
155     }
156 
157     ani_method acquireObj;
158     if (ANI_OK != env->Class_FindMethod(cls, "acquireFileUriEntity", "J:V", &acquireObj)) {
159         LOGE("Not found method acquireFileUriEntity in class LFileUri.");
160         delete holder;
161         ThrowBusinessError(env, EPERM, "Method acquireFileUriEntity not found.");
162         return;
163     }
164 
165     if (ANI_OK != env->Object_CallMethod_Void(obj, acquireObj, reinterpret_cast<ani_long>(holder))) {
166         LOGE("Call method acquireFileUriEntity failed.");
167         delete holder;
168         ThrowBusinessError(env, EPERM, "Call method acquireFileUriEntity failed.");
169         return;
170     }
171 }
172 
ANI_Constructor(ani_vm * vm,uint32_t * result)173 ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
174 {
175     LOGD("Enter ANI_Constructor.");
176     ani_env *env;
177     if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
178         LOGE("Unsupported ANI_VERSION_1");
179         return ANI_ERROR;
180     }
181 
182     static const char *nsName = "L@ohos/file/fileuri/fileUri;";
183     ani_namespace ns;
184     if (ANI_OK != env->FindNamespace(nsName, &ns)) {
185         LOGE("Not found namespace %{public}s.", nsName);
186         return ANI_NOT_FOUND;
187     }
188     std::array nsMethods = {
189         ani_native_function {"getUriFromPath", nullptr, reinterpret_cast<void *>(GetUriFromPath)},
190     };
191     if (ANI_OK != env->Namespace_BindNativeFunctions(ns, nsMethods.data(), nsMethods.size())) {
192         LOGE("Cannot bind native methods to namespace %{public}s.", nsName);
193         return ANI_ERROR;
194     };
195 
196     static const char *className = "LFileUri;";
197     ani_class fileUriClass;
198     if (ANI_OK != env->Namespace_FindClass(ns, className, &fileUriClass)) {
199         LOGE("Not found class %{public}s in %{public}s.", nsName, nsName);
200         return ANI_NOT_FOUND;
201     }
202     std::array classMethods = {
203         ani_native_function {"<ctor>", "Lstd/core/String;:V", reinterpret_cast<void *>(FileUriConstructor)},
204     };
205     if (ANI_OK != env->Class_BindNativeMethods(fileUriClass, classMethods.data(), classMethods.size())) {
206         LOGE("Cannot bind native methods to class %{public}s.", className);
207         return ANI_ERROR;
208     };
209 
210     ani_class cleanerCls;
211     if (ANI_OK != env->FindClass("L@ohos/file/fileuri/Cleaner;", &cleanerCls)) {
212         LOGE("Not found class @ohos/file/fileuri/Cleaner;.");
213         return ANI_NOT_FOUND;
214     }
215     NativePtrCleaner(env).Bind(cleanerCls);
216 
217     *result = ANI_VERSION_1;
218     return ANI_OK;
219 }
220