Basename bug fixed
[platform/core/dotnet/launcher.git] / NativeLauncher / launcher / dotnet / dotnet_launcher.cc
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18 #include <dlfcn.h>
19
20 #include <string>
21 #include <fstream>
22 #include <vector>
23
24 #include "utils.h"
25 #include "log.h"
26 #include "launcher.h"
27 #include "dotnet_launcher.h"
28
29 namespace tizen {
30 namespace runtime {
31 namespace dotnetcore {
32
33 CoreRuntime::CoreRuntime() :
34   InitializeClr(nullptr),
35   ExecuteAssembly(nullptr),
36   Shutdown(nullptr),
37   CreateDelegate(nullptr),
38   coreclrLib(nullptr),
39   hostHandle(nullptr),
40   domainId(-1),
41   PreparedFunction(nullptr),
42   LaunchFunction(nullptr)
43 {
44 #define __XSTR(x) #x
45 #define __STR(x) __XSTR(x)
46
47 #ifdef DEVICE_API_DIR
48   DeviceAPIDirectory = __STR(DEVICE_API_DIR);
49 #endif
50 #ifdef RUNTIME_DIR
51   RuntimeDirectory = __STR(RUNTIME_DIR);
52 #endif
53 #ifdef NATIVE_LIB_DIR
54   NativeLibDirectory = __STR(NATIVE_LIB_DIR);
55 #endif
56
57 #ifdef USE_MANAGED_LAUNCHER
58 #ifdef CORECLR_LAUNCHER_ASSEMBLY_PATH
59   LauncherAssembly = __STR(CORECLR_LAUNCHER_ASSEMBLY_PATH);
60 #endif
61 #endif
62
63 #undef __STR
64 #undef __XSTR
65
66   _DBG("Constructor called!!");
67 }
68
69 CoreRuntime::~CoreRuntime()
70 {
71   Dispose();
72 }
73
74 int CoreRuntime::Initialize(bool standalone)
75 {
76   if (standalone)
77   {
78     const char *_deviceapi_directory = getenv("DeviceAPIDirectory");
79     const char *_runtime_directory = getenv("RuntimeDirectory");
80     if (_deviceapi_directory != nullptr)
81       DeviceAPIDirectory = _deviceapi_directory;
82     if (_runtime_directory != nullptr)
83       RuntimeDirectory = _runtime_directory;
84
85 #ifdef USE_MANAGED_LAUNCHER
86     const char *_launcher_assembly = getenv("LauncherAssembly");
87     if (_launcher_assembly != nullptr)
88       LauncherAssembly = _launcher_assembly;
89 #endif
90   }
91
92   if (DeviceAPIDirectory.empty())
93   {
94     _ERR("Empty Device API Directory");
95     return 1;
96   }
97   else
98   {
99     DeviceAPIDirectory = AbsolutePath(DeviceAPIDirectory);
100   }
101
102   if (RuntimeDirectory.empty())
103   {
104     _ERR("Empty Runtime Directory");
105     return 1;
106   }
107   else
108   {
109     RuntimeDirectory = AbsolutePath(RuntimeDirectory);
110   }
111
112 #ifdef USE_MANAGED_LAUNCHER
113   if (LauncherAssembly.empty())
114   {
115     _ERR("Empty Launcher Assembly");
116     return 1;
117   }
118   else
119   {
120     LauncherAssembly = AbsolutePath(LauncherAssembly);
121   }
122 #endif
123
124   std::string libcoreclr(ConcatPath(RuntimeDirectory, "libcoreclr.so"));
125
126   _DBG("libcoreclr : %s", libcoreclr.c_str());
127
128   coreclrLib = dlopen(libcoreclr.c_str(), RTLD_NOW | RTLD_LOCAL);
129   if (coreclrLib == nullptr)
130   {
131     char *err = dlerror();
132     _ERR("dlopen failed to open libcoreclr.so with error %s", err);
133     return 1;
134   }
135
136 #define CORELIB_RETURN_IF_NOSYM(type, variable, name) \
137   do { variable = (type)dlsym(coreclrLib, name); \
138     if (variable == nullptr) { \
139       _ERR(name " is not found in the libcoreclr.so"); \
140       return 1; \
141     }} while(0)
142
143   CORELIB_RETURN_IF_NOSYM(coreclr_initialize_ptr, InitializeClr, "coreclr_initialize");
144   CORELIB_RETURN_IF_NOSYM(coreclr_execute_assembly_ptr, ExecuteAssembly, "coreclr_execute_assembly");
145   CORELIB_RETURN_IF_NOSYM(coreclr_shutdown_ptr, Shutdown, "coreclr_shutdown");
146   CORELIB_RETURN_IF_NOSYM(coreclr_create_delegate_ptr, CreateDelegate, "coreclr_create_delegate");
147
148 #undef CORELIB_RETURN_IF_NOSYM
149
150   _DBG("libcoreclr dlopen and dlsym success");
151
152   _DBG("this addr : %x", this);
153   _DBG("coreclr_initialize : %x", InitializeClr);
154
155   return 0;
156 }
157
158 bool CoreRuntime::InitializeCoreClr(const char* app_id,
159                                     const char* assembly_probe_paths,
160                                     const char* pinvoke_probe_paths,
161                                     const char* tpa_list)
162 {
163   const char *propertyKeys[] =
164   {
165     "TRUSTED_PLATFORM_ASSEMBLIES",
166     "APP_PATHS",
167     "APP_NI_PATHS",
168     "NATIVE_DLL_SEARCH_DIRECTORIES",
169     "AppDomainCompatSwitch"
170   };
171
172   const char *propertyValues[] =
173   {
174     tpa_list,
175     assembly_probe_paths,
176     assembly_probe_paths,
177     pinvoke_probe_paths,
178     "UseLatestBehaviorWhenTFMNotSpecified"
179   };
180
181   std::string selfPath = ReadSelfPath();
182
183   int st = InitializeClr(
184       selfPath.c_str(),
185       app_id,
186       sizeof(propertyKeys) / sizeof(propertyKeys[0]),
187       propertyKeys,
188       propertyValues,
189       &hostHandle,
190       &domainId);
191
192   if (st < 0)
193   {
194     _ERR("initialize core clr fail! (0x%08x)", st);
195     return false;
196   }
197
198   _DBG("Initialize core clr success");
199   return true;
200 }
201
202 int CoreRuntime::RunManagedLauncher(const char* app_id, const char* app_base, const char* tpa_list)
203 {
204   if (FileNotExist(LauncherAssembly))
205   {
206     _ERR("Launcher assembly is not exist in %s", LauncherAssembly.c_str());
207     return 1;
208   }
209
210   if (!InitializeCoreClr(app_id, app_base, app_base, tpa_list))
211   {
212     _ERR("Failed to initialize coreclr");
213     return 1;
214   }
215
216 #ifdef USE_MANAGED_LAUNCHER
217   void *preparedFunctionDelegate;
218   int st = CreateDelegate(hostHandle, domainId,
219       "Tizen.Runtime.Coreclr",
220       "Tizen.Runtime.Coreclr.AssemblyManager",
221       "Prepared", &preparedFunctionDelegate);
222   if (st < 0)
223   {
224     _ERR("Create delegate for Launch prepared function is fail (0x%08x)", st);
225     return 1;
226   }
227   PreparedFunction = reinterpret_cast<PreparedFunctionPtr>(preparedFunctionDelegate);
228
229   if(PreparedFunction != nullptr)
230   {
231     PreparedFunction();
232   }
233
234   void *launchFunctionDelegate;
235   st = CreateDelegate(hostHandle, domainId,
236       "Tizen.Runtime.Coreclr",
237       "Tizen.Runtime.Coreclr.AssemblyManager",
238       "Launch", &launchFunctionDelegate);
239   if (st < 0)
240   {
241     _ERR("Create delegate for Launch managed function is fail! (0x%08x)", st);
242     return 1;
243   }
244   LaunchFunction = reinterpret_cast<LaunchFunctionPtr>(launchFunctionDelegate);
245 #endif
246   return 0;
247 }
248
249 void CoreRuntime::Dispose()
250 {
251   if (hostHandle != nullptr)
252   {
253     int st = Shutdown(hostHandle, domainId);
254     if (st < 0)
255     {
256       _ERR("shutdown core clr fail! (0x%08x)", st);
257     }
258   }
259
260   if (dlclose(coreclrLib) != 0)
261   {
262     _ERR("libcoreclr.so close failed");
263   }
264   coreclrLib = nullptr;
265
266   _DBG("Dotnet runtime disposed");
267 }
268
269 int CoreRuntime::Launch(const char* app_id, const char* root, const char* path, int argc, char* argv[])
270 {
271   if (path == nullptr)
272   {
273     _ERR("executable path is null");
274     return 1;
275   }
276
277   if (FileNotExist(path))
278   {
279     _ERR("File not exist : %s", path);
280     return 1;
281   }
282
283   std::string tpa;
284   std::string appRoot = root;
285   std::string appBin = ConcatPath(appRoot, "bin");
286   std::string appLib = ConcatPath(appRoot, "lib");
287   std::string probePath = appBin + ":" + appLib + ":" + NativeLibDirectory;
288
289   std::vector<std::string> searchDirectories;
290   searchDirectories.push_back(appBin);
291   searchDirectories.push_back(appLib);
292   searchDirectories.push_back(RuntimeDirectory);
293   searchDirectories.push_back(DeviceAPIDirectory);
294 #ifdef USE_MANAGED_LAUNCHER
295   searchDirectories.push_back(Basename(LauncherAssembly));
296 #endif
297
298   AssembliesInDirectory(searchDirectories, tpa);
299
300 #ifdef USE_MANAGED_LAUNCHER
301   RunManagedLauncher(app_id, probePath.c_str(), tpa.c_str());
302
303   bool success = false;
304   if (LaunchFunction != nullptr)
305   {
306     std::string cpppath(path);
307
308     if (IsManagedAssembly(cpppath) && !IsNativeImage(cpppath))
309     {
310       size_t extindex = cpppath.size() - 4;
311       cpppath = cpppath.substr(0, extindex) + ".ni" + cpppath.substr(extindex, 4);
312       if (!FileNotExist(cpppath))
313       {
314         path = cpppath.c_str();
315       }
316     }
317
318     success = LaunchFunction(root, path, argc, argv);
319     if (!success)
320     {
321       _ERR("Failed to launch Application %s", path);
322     }
323     return success ? 0 : 1;
324   }
325   else
326   {
327     _ERR("Failed to find launch function");
328     return 1;
329   }
330 #else
331   int st = InitializeCoreClr(app_id, probePath.c_str(), probePath.c_str(), tpa.c_str());
332   unsigned int ret = 0;
333   st = ExecuteAssembly(hostHandle, domainId, argc, (const char**)argv, path, &ret);
334   if (st < 0)
335   {
336     _ERR("Failed to Execute Assembly %s (0x%08x)", path, st);
337   }
338   return ret;
339 #endif
340 }
341
342 }  // namespace dotnetcore
343 }  // namespace runtime
344 }  // namespace tizen