initialize new launcher
authorpius.lee <pius.lee@samsung.com>
Fri, 23 Sep 2016 07:22:02 +0000 (16:22 +0900)
committerpius.lee <pius.lee@samsung.com>
Fri, 23 Sep 2016 07:22:02 +0000 (16:22 +0900)
Change-Id: I52436781fcc1e00d5e0eace4500b999e4a69ed80

18 files changed:
NativeLauncher/CMakeLists.txt
NativeLauncher/inc/launcher.h [new file with mode: 0644]
NativeLauncher/inc/log.h [moved from NativeLauncher/src/log.h with 100% similarity]
NativeLauncher/inc/utils.h [new file with mode: 0644]
NativeLauncher/src/dotnet/base64.cc [new file with mode: 0644]
NativeLauncher/src/dotnet/base64.h [new file with mode: 0644]
NativeLauncher/src/dotnet/dotnet_launcher.cc [new file with mode: 0644]
NativeLauncher/src/dotnet/dotnet_launcher.h [new file with mode: 0644]
NativeLauncher/src/environment.h [deleted file]
NativeLauncher/src/launcher.cc
NativeLauncher/src/launcher.h [deleted file]
NativeLauncher/src/tini.hpp [deleted file]
NativeLauncher/src/utils.cc [new file with mode: 0644]
NativeLauncher/src/waiter/waiter.cc [moved from NativeLauncher/src/waiter.cc with 100% similarity]
NativeLauncher/src/waiter/waiter.h [moved from NativeLauncher/src/waiter.h with 100% similarity]
Tizen.Runtime/Tizen.Runtime/AssemblyManager.cs
packaging/dotnet-launcher.spec
test_build_on_desktop.sh

index d2ef94e..203ffb7 100644 (file)
@@ -30,7 +30,7 @@ IF(DEFINED RUNTIME_DIR)
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DRUNTIME_DIR=${RUNTIME_DIR}")
 ENDIF(DEFINED RUNTIME_DIR)
 
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -std=c++11")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -pthread -std=c++11 -Wl,--no-as-needed")
 SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,-zdefs" )
 #SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
 SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fPIE")
@@ -43,31 +43,29 @@ SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
 SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
 SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
 
-SET(${PROJECT_NAME}_SOURCE_FILES
+INCLUDE_DIRECTORIES(inc)
+
+SET(DOTNET_LAUNCHER "dotnet-launcher")
+SET(MONO_LAUNCHER "mono-launcher")
+
+SET(${DOTNET_LAUNCHER}_SOURCE_FILES
+       src/utils.cc
        src/launcher.cc
-       src/waiter.cc
+       src/dotnet/dotnet_launcher.cc
+       src/dotnet/base64.cc
 )
-
-ADD_EXECUTABLE(${PROJECT_NAME} ${${PROJECT_NAME}_SOURCE_FILES})
+ADD_EXECUTABLE(${DOTNET_LAUNCHER} ${${PROJECT_NAME}_SOURCE_FILES})
 
 IF(NOT DEFINED NO_TIZEN)
-       TARGET_LINK_LIBRARIES(${PROJECT_NAME} aul)
+       TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER} aul)
 ENDIF(NOT DEFINED NO_TIZEN)
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl")
+TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl -lpthread")
 
-SET_TARGET_PROPERTIES(${PROJECT_NAME}
+SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER}
        PROPERTIES SKIP_BUILD_RPATH TRUE
        ) # remove rpath option that is automatically generated by cmake.
 
-SET(LAUNCHER_LIB "dnclauncher")
-ADD_LIBRARY(${LAUNCHER_LIB} SHARED src/waiter.cc)
-IF(NOT DEFINED NO_TIZEN)
-       TARGET_LINK_LIBRARIES(${LAUNCHER_LIB} aul)
-ENDIF(NOT DEFINED NO_TIZEN)
-TARGET_LINK_LIBRARIES(${LAUNCHER_LIB} ${${PROJECT_NAME}_LDFLAGS} "-ldl")
-
 IF(NOT DEFINED NO_TIZEN)
-       INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${BINDIR})
-       INSTALL(TARGETS ${LAUNCHER_LIB} DESTINATION ${LIBDIR})
+       INSTALL(TARGETS ${DOTNET_LAUNCHER} DESTINATION ${BINDIR})
        INSTALL(FILES dotnet.loader DESTINATION ${LOADERDIR})
 ENDIF(NOT DEFINED NO_TIZEN)
diff --git a/NativeLauncher/inc/launcher.h b/NativeLauncher/inc/launcher.h
new file mode 100644 (file)
index 0000000..f4309b4
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef __LAUNCHER_INTERFACE_H__
+#define __LAUNCHER_INTERFACE_H__
+
+namespace tizen {
+namespace runtime {
+
+class LauncherInterface
+{
+  public:
+    virtual int Initialize() = 0;
+    virtual void Dispose() = 0;
+    virtual int RunManagedLauncher() = 0;
+    virtual int Launch(const char* path, int argc, char* argv[]) = 0;
+};
+
+class LaunchpadAdapter
+{
+  public:
+    virtual void LoaderMain(LauncherInterface* launcher, int argc, char* argv[]) = 0;
+    virtual void WaitUtilLaunched() = 0;
+
+  protected:
+    virtual void OnCreate() = 0;
+    virtual void OnLaunch() = 0;
+    virtual void OnTerminate() = 0;
+};
+
+extern LaunchpadAdapter& Launchpad;
+
+}  // namespace runtime
+}  // namespace tizen
+
+#endif  // __LAUNCHER_INTERFACE_H__
diff --git a/NativeLauncher/inc/utils.h b/NativeLauncher/inc/utils.h
new file mode 100644 (file)
index 0000000..145a43d
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __UTILS_H__
+#define __UTILS_H__
+
+#include <string>
+#include <vector>
+
+#ifndef PATH_SEPARATOR
+#define PATH_SEPARATOR '/'
+#endif
+
+std::string ReadSelfPath ();
+std::string ConcatPath (const std::string& path1, const std::string& path2);
+void AppendPath (std::string& path1, const std::string& path2);
+std::string AbsolutePath (const std::string& path);
+std::string Basename (const std::string& path);
+bool EndWithIgnoreCase (const std::string& str1, const std::string& str2, std::string& filename);
+void AssembliesInDirectory(const std::vector<std::string>& directories, std::string& tpaList);
+bool FileNotExist(const std::string& path);
+std::string JoinStrings(const std::vector<std::string>& strings, const char* const delimeter);
+
+#endif  // __UTILS_H__
diff --git a/NativeLauncher/src/dotnet/base64.cc b/NativeLauncher/src/dotnet/base64.cc
new file mode 100644 (file)
index 0000000..3330082
--- /dev/null
@@ -0,0 +1,94 @@
+#include "base64.h"
+#include <iostream>
+
+static const std::string base64_chars = 
+"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+"abcdefghijklmnopqrstuvwxyz"
+"0123456789+/";
+
+
+static inline bool is_base64(BYTE c) {
+  return (isalnum(c) || (c == '+') || (c == '/'));
+}
+
+std::string base64_encode(BYTE const* buf, unsigned int bufLen) {
+  std::string ret;
+  int i = 0;
+  int j = 0;
+  BYTE char_array_3[3];
+  BYTE char_array_4[4];
+
+  while (bufLen--) {
+    char_array_3[i++] = *(buf++);
+    if (i == 3) {
+      char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+      char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+      char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+      char_array_4[3] = char_array_3[2] & 0x3f;
+
+      for(i = 0; (i <4) ; i++)
+        ret += base64_chars[char_array_4[i]];
+      i = 0;
+    }
+  }
+
+  if (i)
+  {
+    for(j = i; j < 3; j++)
+      char_array_3[j] = '\0';
+
+    char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+    char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+    char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+    char_array_4[3] = char_array_3[2] & 0x3f;
+
+    for (j = 0; (j < i + 1); j++)
+      ret += base64_chars[char_array_4[j]];
+
+    while((i++ < 3))
+      ret += '=';
+  }
+
+  return ret;
+}
+
+std::vector<BYTE> base64_decode(std::string const& encoded_string) {
+  int in_len = encoded_string.size();
+  int i = 0;
+  int j = 0;
+  int in_ = 0;
+  BYTE char_array_4[4], char_array_3[3];
+  std::vector<BYTE> ret;
+
+  while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
+    char_array_4[i++] = encoded_string[in_]; in_++;
+    if (i ==4) {
+      for (i = 0; i <4; i++)
+        char_array_4[i] = base64_chars.find(char_array_4[i]);
+
+      char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
+      char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
+      char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
+
+      for (i = 0; (i < 3); i++)
+        ret.push_back(char_array_3[i]);
+      i = 0;
+    }
+  }
+
+  if (i) {
+    for (j = i; j <4; j++)
+      char_array_4[j] = 0;
+
+    for (j = 0; j <4; j++)
+      char_array_4[j] = base64_chars.find(char_array_4[j]);
+
+    char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
+    char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
+    char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
+
+    for (j = 0; (j < i - 1); j++) ret.push_back(char_array_3[j]);
+  }
+
+  return ret;
+}
diff --git a/NativeLauncher/src/dotnet/base64.h b/NativeLauncher/src/dotnet/base64.h
new file mode 100644 (file)
index 0000000..1a6b6ba
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _BASE64_H_
+#define _BASE64_H_
+
+#include <vector>
+#include <string>
+typedef unsigned char BYTE;
+
+std::string base64_encode(BYTE const* buf, unsigned int bufLen);
+std::vector<BYTE> base64_decode(std::string const&);
+
+#endif
diff --git a/NativeLauncher/src/dotnet/dotnet_launcher.cc b/NativeLauncher/src/dotnet/dotnet_launcher.cc
new file mode 100644 (file)
index 0000000..4942710
--- /dev/null
@@ -0,0 +1,348 @@
+
+#include <dlfcn.h>
+
+#include <string>
+#include <fstream>
+#include <thread>
+#include <vector>
+
+#include "utils.h"
+#include "log.h"
+#include "launcher.h"
+#include "dotnet_launcher.h"
+
+namespace tizen {
+namespace runtime {
+namespace dotnetcore {
+
+
+void CoreRuntime::SetStandaloneExe(const char* exePath, int argc, char* argv[])
+{
+  if (exePath == nullptr)
+  {
+    _ERR("executable path is null");
+    return;
+  }
+
+  if (FileNotExist(exePath))
+  {
+    _ERR("File not exist : %s", exePath);
+    return;
+  }
+
+  isLaunched = true;
+  LaunchParam.path = exePath;
+  LaunchParam.argc = argc;
+  LaunchParam.argv = argv;
+
+  const char *_deviceapi_directory = getenv("DeviceAPIDirectory");
+  const char *_runtime_directory = getenv("RuntimeDirectory");
+  const char *_launcher_assembly = getenv("LauncherAssembly");
+  if (_deviceapi_directory != nullptr)
+    DeviceAPIDirectory = _deviceapi_directory;
+  if (_runtime_directory != nullptr)
+    RuntimeDirectory = _runtime_directory;
+  if (_launcher_assembly != nullptr)
+    LauncherAssembly = _launcher_assembly;
+}
+
+CoreRuntime::CoreRuntime() :
+  coreclrLib(nullptr),
+  hostHandle(nullptr),
+  domainId(-1),
+  LaunchFunction(nullptr),
+  isLaunched(false),
+  InitializeClr(nullptr),
+  ExecuteAssembly(nullptr),
+  Shutdown(nullptr),
+  CreateDelegate(nullptr)
+{
+#define __XSTR(x) #x
+#define __STR(x) __XSTR(x)
+
+#ifdef DEVICE_API_DIR
+  DeviceAPIDirectory = __STR(DEVICE_API_DIR);
+#endif
+#ifdef RUNTIME_DIR
+  RuntimeDirectory = __STR(RUNTIME_DIR);
+#endif
+#ifdef LAUNCHER_ASSEMBLY_PATH
+  LauncherAssembly = __STR(LAUNCHER_ASSEMBLY_PATH);
+#endif
+
+#undef __STR
+#undef __XSTR
+
+  _DBG("Constructor called!!");
+}
+
+CoreRuntime::~CoreRuntime()
+{
+  Dispose();
+}
+
+int CoreRuntime::Initialize()
+{
+
+  if (DeviceAPIDirectory.empty())
+  {
+    _ERR("Empty Device API Directory");
+    return 1;
+  }
+  else
+  {
+    DeviceAPIDirectory = AbsolutePath(DeviceAPIDirectory);
+  }
+  if (RuntimeDirectory.empty())
+  {
+    _ERR("Empty Runtime Directory");
+    return 1;
+  }
+  else
+  {
+    RuntimeDirectory = AbsolutePath(RuntimeDirectory);
+  }
+  if (LauncherAssembly.empty())
+  {
+    _ERR("Empty Launcher Assembly");
+    return 1;
+  }
+  else
+  {
+    LauncherAssembly = AbsolutePath(LauncherAssembly);
+  }
+
+  std::string libcoreclr(ConcatPath(RuntimeDirectory, "libcoreclr.so"));
+
+  _DBG("libcoreclr : %s", libcoreclr.c_str());
+
+  coreclrLib = dlopen(libcoreclr.c_str(), RTLD_NOW | RTLD_LOCAL);
+  if (coreclrLib == nullptr)
+  {
+    char *err = dlerror();
+    _ERR("dlopen failed to open libcoreclr.so with error %s", err);
+    return 1;
+  }
+
+#define CORELIB_RETURN_IF_NOSYM(type, variable, name) \
+  do { variable = (type)dlsym(coreclrLib, name); \
+    if (variable == nullptr) { \
+      _ERR(name " is not found in the libcoreclr.so"); \
+      return 1; \
+    }} while(0)
+
+  CORELIB_RETURN_IF_NOSYM(coreclr_initialize_ptr, InitializeClr, "coreclr_initialize");
+  CORELIB_RETURN_IF_NOSYM(coreclr_execute_assembly_ptr, ExecuteAssembly, "coreclr_execute_assembly");
+  CORELIB_RETURN_IF_NOSYM(coreclr_shutdown_ptr, Shutdown, "coreclr_shutdown");
+  CORELIB_RETURN_IF_NOSYM(coreclr_create_delegate_ptr, CreateDelegate, "coreclr_create_delegate");
+
+#undef CORELIB_RETURN_IF_NOSYM
+
+  _DBG("libcoreclr dlopen and dlsym success");
+
+  _DBG("this addr : %x", this);
+  _DBG("coreclr_initialize : %x", InitializeClr);
+
+  return 0;
+}
+
+int CoreRuntime::RunManagedLauncher()
+{
+  void* hostHandle;
+  unsigned int domainId;
+
+  if (FileNotExist(LauncherAssembly))
+  {
+    _ERR("Launcher assembly is not exist in %s", LauncherAssembly.c_str());
+    return 1;
+  }
+
+  std::string launcherDir = Basename(LauncherAssembly);
+  std::vector<std::string> searchDirectories = {
+    RuntimeDirectory, DeviceAPIDirectory, launcherDir
+  };
+
+  std::string trusted_assemblies;
+  AssembliesInDirectory(searchDirectories, trusted_assemblies);
+  std::string trusted_directories = JoinStrings(searchDirectories, ":");
+
+  _DBG("coreclr_dir : %s", RuntimeDirectory.c_str());
+  _DBG("tpa_dirs : %s", trusted_directories.c_str());
+  _DBG("native_so_search_dir : %s", trusted_directories.c_str());
+  _DBG("launcher_assembly : %s", LauncherAssembly.c_str());
+  _DBG("launcher_dir : %s", launcherDir.c_str());
+
+  const char *propertyKeys[] =
+  {
+    "TRUSTED_PLATFORM_ASSEMBLIES",
+    "APP_PATHS",
+    "APP_NI_PATHS",
+    "NATIVE_DLL_SEARCH_DIRECTORIES",
+    "AppDomainCompatSwitch"
+  };
+
+  const char *propertyValues[] =
+  {
+    trusted_assemblies.c_str(),
+    launcherDir.c_str(),
+    launcherDir.c_str(),
+    trusted_directories.c_str(),
+    "UseLatestBehaviorWhenTFMNotSpecified"
+  };
+  
+//  _DBG("trusted platform assemblies : %s", propertyValues[0]);
+  _DBG("app_path : %s", propertyValues[1]);
+  _DBG("app_ni_path : %s", propertyValues[2]);
+  _DBG("native dll search path : %s", propertyValues[3]);
+  _DBG("app domain compat switch : %s", propertyValues[4]);
+
+  _DBG("before InitializeClr");
+  _DBG("this addr : %x", this);
+  _DBG("coreclr_initialize : %x", InitializeClr);
+
+  std::string selfPath = ReadSelfPath();
+
+  _DBG("self path : %s", selfPath.c_str());
+
+  _DBG("libcoreclr addr : %x", coreclrLib);
+
+  int st = InitializeClr(
+      selfPath.c_str(),
+      //LauncherAssembly.c_str(),
+      "dotnet-launcher",
+      sizeof(propertyKeys) / sizeof(propertyKeys[0]),
+      propertyKeys,
+      propertyValues,
+      &hostHandle,
+      &domainId);
+
+  if (st < 0)
+  {
+    _ERR("initialize core clr fail! (0x%08x)", st);
+    return 1;
+  }
+
+  _DBG("Initialize core clr success");
+
+  void *launchFunctionDelegate;
+  st = CreateDelegate(hostHandle, domainId,
+      "Tizen.Runtime",
+      "Tizen.Runtime.AssemblyManager",
+      "Launch", &launchFunctionDelegate);
+  if (st < 0)
+  {
+    _ERR("Create delegate for Launch managed function is fail! (0x%08x)", st);
+    return 1;
+  }
+  LaunchFunction = reinterpret_cast<LaunchFunctionPtr>(launchFunctionDelegate);
+
+  if (isLaunched)
+  {
+    bool success = LaunchFunction(LaunchParam.path.c_str(),
+        LaunchParam.argc, LaunchParam.argv);
+    if (!success)
+    {
+      _ERR("Failed to Launching");
+    }
+  }
+
+  /*
+  unsigned int exitCode;
+  const char* argv[] = {LauncherAssembly.c_str()};
+  st = ExecuteAssembly(hostHandle, domainId,
+      1, argv, LauncherAssembly.c_str(), &exitCode);
+  _DBG("after execute coreclr");
+  if (st < 0)
+  {
+    _ERR("execute core clr fail! (0x%08x / %d)", st, exitCode);
+    return 1;
+  }
+  */
+
+  return 0;
+}
+
+void CoreRuntime::Dispose()
+{
+  if (hostHandle != nullptr)
+  {
+    int st = Shutdown(hostHandle, domainId);
+    if (st < 0)
+    {
+      _ERR("shutdown core clr fail! (0x%08x)", st);
+    }
+  }
+
+  if (dlclose(coreclrLib) != 0)
+  {
+    _ERR("libcoreclr.so close failed");
+  }
+  coreclrLib = nullptr;
+
+  _DBG("Dotnet runtime disposed");
+}
+
+int CoreRuntime::Launch(const char* path, int argc, char* argv[])
+{
+  if (LaunchFunction != nullptr)
+  {
+    LaunchFunction(path, argc, argv);
+  }
+  else
+  {
+    LaunchParam.path = path;
+    LaunchParam.argc = argc;
+    LaunchParam.argv = argv;
+  }
+  isLaunched = true;
+
+  return 0;
+}
+
+}  // namespace dotnetcore
+}  // namespace runtime
+}  // namespace tizen
+
+static std::string StandaloneOption("--standalone");
+
+#include "base64.h"
+
+int main(int argc, char *argv[])
+{
+  int i;
+  bool standalone = false;
+  const char* standalonePath = nullptr;
+
+  for (i=1; i<argc; i++)
+  {
+    if (StandaloneOption.compare(argv[i]) == 0)
+    {
+      standalone = true;
+    }
+    else
+    {
+      if (standalonePath == nullptr)
+        standalonePath = argv[i];
+    }
+  }
+
+  tizen::runtime::dotnetcore::CoreRuntime runtime;
+  if (standalone)
+  {
+    runtime.SetStandaloneExe(standalonePath, argc, argv);
+  }
+  else
+  {
+    tizen::runtime::Launchpad.LoaderMain(&runtime, argc, argv);
+  }
+
+  runtime.Initialize();
+  runtime.RunManagedLauncher();
+
+  if (!standalone)
+  {
+    tizen::runtime::Launchpad.WaitUtilLaunched();
+  }
+
+  return 0;
+}
diff --git a/NativeLauncher/src/dotnet/dotnet_launcher.h b/NativeLauncher/src/dotnet/dotnet_launcher.h
new file mode 100644 (file)
index 0000000..e1a86b0
--- /dev/null
@@ -0,0 +1,77 @@
+#include "launcher.h"
+
+extern "C"
+{
+  typedef int (*coreclr_initialize_ptr)(
+      const char* exePath,
+      const char* appDomainFriendlyName,
+      int propertyCount,
+      const char** propertyKeys,
+      const char** propertyValues,
+      void** hostHandle,
+      unsigned int* domainId);
+
+  typedef int (*coreclr_execute_assembly_ptr)(
+      void* hostHandle,
+      unsigned int domainId,
+      int argc,
+      const char** argv,
+      const char* managedAssemblyPath,
+      unsigned int* exitCode);
+
+  typedef int (*coreclr_shutdown_ptr)(
+      void* hostHandle,
+      unsigned int domainId);
+
+  typedef int (*coreclr_create_delegate_ptr)(
+      void* hostHandle,
+      unsigned int domainId,
+      const char* entryPointAssemblyName,
+      const char* entryPointTypeName,
+      const char* entryPointMethodName,
+      void** delegate);
+}
+
+namespace tizen {
+namespace runtime {
+namespace dotnetcore {
+
+typedef bool (*LaunchFunctionPtr)(const char* path, int argc, char* argv[]);
+
+struct LaunchParameter
+{
+  std::string path;
+  int argc;
+  char** argv;
+};
+
+class CoreRuntime : public tizen::runtime::LauncherInterface
+{
+  public:
+    CoreRuntime();
+    ~CoreRuntime();
+    int Initialize() override;
+    void Dispose() override;
+    int RunManagedLauncher() override;
+    int Launch(const char* path, int argc, char* argv[]) override;
+    void SetStandaloneExe(const char* exePath, int argc, char* argv[]);
+
+  private:
+    coreclr_initialize_ptr InitializeClr;
+    coreclr_execute_assembly_ptr ExecuteAssembly;
+    coreclr_shutdown_ptr Shutdown;
+    coreclr_create_delegate_ptr CreateDelegate;
+    std::string DeviceAPIDirectory;
+    std::string RuntimeDirectory;
+    std::string LauncherAssembly;
+    void* coreclrLib;
+    void* hostHandle;
+    unsigned int domainId;
+    LaunchFunctionPtr LaunchFunction;
+    bool isLaunched;
+    LaunchParameter LaunchParam;
+};
+
+}  // dotnetcore
+}  // namespace runtime
+}  // namespace tizen
diff --git a/NativeLauncher/src/environment.h b/NativeLauncher/src/environment.h
deleted file mode 100644 (file)
index 6e4e57b..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __ENVIRONMENT_H__
-
-#ifndef TIZEN_CORECLR_PATH
-#define TIZEN_CORECLR_PATH "/usr/share/coreclr/libcoreclr.so"
-#endif
-
-#ifndef TIZEN_NETCORE_TPA_PATH
-#define TIZEN_NETCORE_TPA_PATH "/usr/share/assemblies"
-#endif
-
-
-#endif // __ENVIRONMENT_H__
index 35762f5..518a1d9 100644 (file)
-#include <dlfcn.h>
-
-#include <cstdlib>
-#include <cstring>
-#include <vector>
-#include <string>
-#include <set>
-#include <sstream>
-#include <fstream>
-#include <memory>
-#include <algorithm>
-
-#include <dirent.h>
-#include <sys/stat.h>
-
-#include <unistd.h>
-#include <limits.h>
-
-#include "environment.h"
-#include "waiter.h"
+#include "launcher.h"
 #include "log.h"
 
-#include "tini.hpp"
-
-#define __XSTR(x) #x
-#define __STR(x) __XSTR(x)
-
-#ifndef NO_TIZEN
-
-#ifndef DEVICE_API_DIR
-  #error "DEVICE_API_DIR must be exist."
-#endif
-
-#ifndef RUNTIME_DIR
-  #error "RUNTIME_DIR must be exist."
-#endif
-
-#ifndef LAUNCHER_ASSEMBLY_PATH
-  #error "LAUNCHER_ASSEMBLY_PATH must be exist."
-#endif
-
-#define CONST const
-#else
-
-#define CONST
-#include <stdlib.h>
-#endif
-
-#ifdef DEVICE_API_DIR
-static CONST std::string DeviceAPIDirectory(__STR(DEVICE_API_DIR));
-#else
-static std::string DeviceAPIDirectory;
-#endif
-#ifdef RUNTIME_DIR
-static CONST std::string RuntimeDirectory(__STR(RUNTIME_DIR));
-#else
-static std::string RuntimeDirectory;
-#endif
-#ifdef LAUNCHER_ASSEMBLY_PATH
-static CONST std::string LauncherAssembly(__STR(LAUNCHER_ASSEMBLY_PATH));
-#else
-static std::string LauncherAssembly;
-#endif
-
-#undef __STR
-#undef __XSTR
-
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR '/'
-#endif
+#include <launchpad.h>
 
-typedef int (*coreclr_initialize_ptr)(
-    const char* exePath,
-    const char* appDomainFriendlyName,
-    int propertyCount,
-    const char** propertyKeys,
-    const char** propertyValues,
-    void** hostHandle,
-    unsigned int* domainId);
+#include <poll.h>
 
-typedef int (*coreclr_execute_assembly_ptr)(
-    void* hostHandle,
-    unsigned int domainId,
-    int argc,
-    const char** argv,
-    const char* managedAssemblyPath,
-    unsigned int* exitCode);
-
-typedef int (*coreclr_shutdown_ptr)(
-    void* hostHandle,
-    unsigned int domainId);
-
-typedef int (*coreclr_create_delegate_ptr)(
-    void* hostHandle,
-    unsigned int domainId,
-    const char* entryPointAssemblyName,
-    const char* entryPointTypeName,
-    const char* entryPointMethodName,
-    void** delegate);
-
-std::string ReadSelfPath() {
-  char buff[PATH_MAX];
-  ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
-  if (len != -1) {
-    buff[len] = '\0';
-    return std::string(buff);
-  }
+#include <map>
+#include <vector>
+#include <functional>
+#include <thread>
 
-  return "";
-}
+namespace tizen {
+namespace runtime {
 
-static std::string ConcatPath(const std::string& path1, const std::string& path2)
+struct FdHandler
 {
-  std::string path(path1);
-  if (path.back() == PATH_SEPARATOR)
-  {
-    path.append(path2);
-  }
-  else
-  {
-    path += PATH_SEPARATOR;
-    path.append(path2);
-  }
+  pollfd *info;
+  std::function<void(int)> receiver;
+};
 
-  return path;
-}
-/*
-static void AppendPath(std::string& path1, const std::string& path2)
+class LaunchpadAdapterImpl : public LaunchpadAdapter
 {
-  if (path1.back() == PATH_SEPARATOR)
-  {
-    path1.append(path2);
-  }
-  else
-  {
-    path1 += PATH_SEPARATOR;
-    path1.append(path2);
-  }
-}
-*/
-
-static std::string AbsolutePath(const std::string& path)
+  public:
+    LaunchpadAdapterImpl() : isLaunched(false) { }
+    void LoaderMain(LauncherInterface* launcher, int argc, char* argv[]) override;
+    void WaitUtilLaunched() override;
+
+  protected:
+    void OnCreate() override;
+    void OnLaunch() override;
+    void OnTerminate() override;
+
+  private:
+    loader_lifecycle_callback_s callbacks;
+    loader_adapter_s adapter;
+    LauncherInterface* launcher;
+    bool isLaunched;
+    std::string launchPath;
+
+    bool Waiting;
+    std::vector<pollfd> FdList;
+    std::map<int, FdHandler> Handlers;
+
+    std::thread pollingThread;
+};
+
+LaunchpadAdapterImpl LaunchpadImpl;
+LaunchpadAdapter& Launchpad = LaunchpadImpl;
+
+void LaunchpadAdapterImpl::LoaderMain(LauncherInterface* launcher, int argc, char* argv[])
 {
-  std::string absPath;
-
-  char realPath[PATH_MAX];
-  if (realpath(path.c_str(), realPath) != nullptr && realPath[0] != '\0')
-  {
-    absPath.assign(realPath);
-  }
+  this->launcher = launcher;
+#define WITH_SELF(data) \
+  LaunchpadAdapterImpl* self = static_cast<LaunchpadAdapterImpl*>(data); \
+  if (self == nullptr) \
+  { \
+    _ERR("No LaunchpadImplData"); \
+  } else
 
-  return absPath;
-}
 
-static std::string Basename(const std::string& path)
-{
-  auto pos = path.find_last_of(PATH_SEPARATOR);
-  if (pos != std::string::npos)
+  callbacks.create = [](bundle *extra, int type, void *user_data)
   {
-    return path.substr(0, pos);
-  }
-  else
-  {
-    return std::string(".");
-  }
-  return path;
-}
-
-static bool EndWithIC(const std::string& str1, const std::string& str2, std::string& filename)
-{
-  std::string::size_type len1 = str1.length();
-  std::string::size_type len2 = str2.length();
-  if (len2 > len1) return false;
-
-  int i = 0;
-  bool result = std::all_of(str1.cend() - len2, str1.end(),
-        [&i, &str2] (char x) {
-          return std::tolower(x) == std::tolower(str2[i++]);
-        });
-  if (result)
+    WITH_SELF(user_data)
+    {
+      self->OnCreate();
+    }
+  };
+  callbacks.launch = [](int argc, char** argv, const char* app_path,
+      const char* appid, const char* pkgid,
+      const char* pkg_type, void* user_data) -> int
   {
-    filename = str1.substr(0, len1 - len2);
-  }
-  return result;
-}
-
-static std::string AssembliesInDirectory(const char *directory)
-{
-  const std::string ni = ".ni";
-  const std::string tpaExtensions[] =
-  {".ni.dll", ".dll", ".ni.exe", ".exe"};
-  const bool tpaExtensions_ni[] =
-  {true, false, true, false};
-
-  std::string tpaList;
-
-  DIR* dir = opendir(directory);
+    WITH_SELF(user_data)
+    {
+      self->OnLaunch();
+      self->launchPath = std::string(app_path);
+    }
 
-  if (dir == nullptr)
+    return 0;
+  };
+  callbacks.terminate = [](int argc, char **argv, void* user_data) -> int
   {
-    _ERR("can not open directory : [%s]", directory);
-    return std::string();
-  }
-
-  _DBG("assemblies in %s", directory);
-
-  std::set<std::string> addedAssemblies;
-
-  struct dirent *entry;
+    _DBG("Terminate!!");
+    WITH_SELF(user_data)
+    {
+      self->OnTerminate();
+      //self->launcher->Launch(self->launchPath.c_str(), argc, argv);
+    }
+    return 0;
+  };
 
-  int tpaCount = sizeof(tpaExtensions) / sizeof(tpaExtensions[0]);
-  for (int i=0; i<tpaCount; i++)
+  adapter.loop_begin = [](void *data)
   {
-    const std::string& ext = tpaExtensions[i];
-    bool isNativeExt = tpaExtensions_ni[i];
-
-    while ((entry = readdir(dir)) != nullptr)
+    _DBG("start polling...");
+    WITH_SELF(data)
     {
-      switch (entry->d_type)
+      self->Waiting = true;
+      while(self->Waiting)
       {
-        case DT_REG: break;
-        case DT_LNK:
-        case DT_UNKNOWN:
-          {
-            std::string fullname;
-            fullname.append(directory);
-            fullname += PATH_SEPARATOR;
-            fullname.append(entry->d_name);
-
-            struct stat sb;
-            if (stat(fullname.c_str(), &sb) == -1)
-              continue;
-
-            if (!S_ISREG(sb.st_mode))
-              continue;
-          }
-          break;
-        default:
+        if (poll(self->FdList.data(), self->FdList.size(), -1) < 0)
           continue;
-      }
-
-      // Check the extension.
-      std::string filename(entry->d_name);
-      std::string filenameWithoutExt;
-      if (!EndWithIC(filename, ext, filenameWithoutExt))
-        continue;
 
-      if (!isNativeExt)
-      {
-        EndWithIC(filenameWithoutExt, ni, filenameWithoutExt);
-      }
-
-      if (addedAssemblies.find(filenameWithoutExt) == addedAssemblies.end())
-      {
-        addedAssemblies.insert(filenameWithoutExt);
-        std::string assembly;
-        assembly.append(directory);
-        assembly += PATH_SEPARATOR;
-        assembly.append(filename);
-        //_DBG("TPA : %s", assembly.c_str());
-        tpaList += assembly + ':';
+        _DBG("-----------------------------------------------------------4");
+        for (auto &p : self->FdList)
+        {
+          if ( (p.revents | POLLIN) != 0)
+            self->Handlers[p.fd].receiver(p.fd);
+        }
+        _DBG("-----------------------------------------------------------5");
       }
     }
-    rewinddir(dir);
-  }
-
-  closedir(dir);
-  return tpaList;
-}
-
-static int RunLauncherDll(int argc, char* argv[])
-{
-  std::string coreclr_dir(RuntimeDirectory);
-  std::string libcoreclr(ConcatPath(coreclr_dir, "libcoreclr.so"));
-  std::string tpa_dirs(coreclr_dir + ":" + DeviceAPIDirectory);
-  std::string native_so_search_dirs(tpa_dirs);
-  std::string launcher_assembly(AbsolutePath(LauncherAssembly));
-
-  if (launcher_assembly.empty())
-  {
-    _ERR("Invalid Launcher assembly path.");
-    return 1;
-  }
-
-  std::string launcher_dir = Basename(launcher_assembly);
-  std::string trusted_assemblies = launcher_assembly + ":";
+    _DBG("end polling...");
+  };
 
-  std::istringstream f(tpa_dirs);
-  std::string s;
-  while (std::getline(f, s, ':'))
+  adapter.loop_quit = [](void *data)
   {
-    trusted_assemblies += AssembliesInDirectory(s.c_str());
-  }
-
-  _DBG("libcoreclr : %s", libcoreclr.c_str());
-  _DBG("coreclr_dir : %s", coreclr_dir.c_str());
-  _DBG("tpa_dirs : %s", tpa_dirs.c_str());
-  _DBG("native_so_search_dir : %s", native_so_search_dirs.c_str());
-  _DBG("launcher_assembly : %s", launcher_assembly.c_str());
-  _DBG("launcher_dir : %s", launcher_dir.c_str());
+    WITH_SELF(data)
+    {
+      self->Waiting = false;
+    }
+  };
 
-  void *coreclrLib = dlopen(libcoreclr.c_str(), RTLD_NOW | RTLD_LOCAL);
-  if (coreclrLib == nullptr)
+  adapter.add_fd = [](void *data, int fd, loader_receiver_cb receiver)
   {
-    char *err = dlerror();
-    _ERR("dlopen failed to open libcoreclr.so with error %s", err);
-    return 1;
-  }
-
-#define CORELIB_RETURN_IF_NOSYM(type, variable, name) \
-  type variable; \
-  do { variable = (type)dlsym(coreclrLib, name); \
-    if (variable == nullptr) { \
-      _ERR(name " is not found in the libcoreclr.so"); \
-      return 1; \
-    }} while(0)
+    WITH_SELF(data)
+    {
+      pollfd info;
+      FdHandler handler;
 
-  CORELIB_RETURN_IF_NOSYM(coreclr_initialize_ptr, coreclr_initialize, "coreclr_initialize");
-  CORELIB_RETURN_IF_NOSYM(coreclr_execute_assembly_ptr, coreclr_execute_assembly, "coreclr_execute_assembly");
-  CORELIB_RETURN_IF_NOSYM(coreclr_shutdown_ptr, coreclr_shutdown, "coreclr_shutdown");
-  CORELIB_RETURN_IF_NOSYM(coreclr_create_delegate_ptr, coreclr_create_delegate, "coreclr_create_delegate");
+      info.fd = fd;
+      info.events = POLLIN;
+      info.revents = 0;
 
-#undef CORELIB_RETURN_IF_NOSYM
+      self->FdList.push_back(info);
+      handler.info = &((self->FdList).back());
+      handler.receiver = receiver;
 
-  const char *propertyKeys[] =
-  {
-    "TRUSTED_PLATFORM_ASSEMBLIES",
-    "APP_PATHS",
-    "APP_NI_PATHS",
-    "NATIVE_DLL_SEARCH_DIRECTORIES",
-    "AppDomainCompatSwitch"
+      self->Handlers[fd] = handler;
+    }
   };
 
-  const char *propertyValues[] =
+  adapter.remove_fd = [](void *user_data, int fd)
   {
-    trusted_assemblies.c_str(),
-    launcher_dir.c_str(),
-    launcher_dir.c_str(),
-    native_so_search_dirs.c_str(),
-    "UseLatestBehaviorWhenTFMNotSpecified"
+    WITH_SELF(user_data)
+    {
+      pollfd *info = self->Handlers[fd].info;
+      self->FdList.erase(self->FdList.begin() - (info - &(self->FdList.front())));
+      self->Handlers.erase(fd);
+    }
   };
 
-  //_DBG("trusted platform assemblies : %s", propertyValues[0]);
-  _DBG("app_path : %s", propertyValues[1]);
-  _DBG("app_ni_path : %s", propertyValues[2]);
-  _DBG("native dll search path : %s", propertyValues[3]);
-  _DBG("app domain compat switch : %s", propertyValues[4]);
-
-  _DBG("before initialize coreclr");
-
-  void* hostHandle;
-  unsigned int domainId;
-
-  std::string selfPath = ReadSelfPath();
-
-  int st = coreclr_initialize(selfPath.c_str(),
-      "tizen_dotnet_launcher",
-      sizeof(propertyKeys) / sizeof(propertyKeys[0]),
-      propertyKeys,
-      propertyValues,
-      &hostHandle,
-      &domainId);
-
-  _DBG("after initialize coreclr");
-  if (st < 0)
-  {
-    // initialize coreclr fail
-    _ERR("initialize core clr fail! (0x%08x)", st);
-    _DBG("check your smack label dll and every directories on the way to dlls");
-    return 1;
-  }
-
-  struct stat sb;
-  if (stat(launcher_assembly.c_str(), &sb) == -1)
+  pollingThread = std::thread([this, argc, argv]()
   {
-    _ERR("Launcher assembly is not exist in %s", launcher_assembly.c_str());
-    return 1;
-  }
+    _DBG("launchpad_loader_main is start");
+    int r = launchpad_loader_main(argc, argv, &(this->callbacks), &(this->adapter), this);
+    _DBG("launchpad_loader_main is finished with [%d]", r);
+  });
+  //pollingThread.detach();
+}
 
-  unsigned int exitCode;
-  const char** cargv = const_cast<const char**>(argv);
-  st = coreclr_execute_assembly(hostHandle, domainId,
-      argc, cargv, launcher_assembly.c_str(), &exitCode);
-  _DBG("after execute coreclr");
-  if (st < 0)
+void LaunchpadAdapterImpl::WaitUtilLaunched()
+{
+  try
   {
-    _ERR("execute core clr fail! (0x%08x / %d)", st, exitCode);
-    return 1;
+    if (pollingThread.joinable())
+    {
+      pollingThread.join();
+    }
   }
-
-  st = coreclr_shutdown(hostHandle, domainId);
-  if (st < 0)
+  catch (const std::exception& ex)
   {
-    _ERR("shutdown core clr fail! (0x%08x)", st);
-    return 1;
+    _ERR("Exception  : %s", ex.what());
   }
+}
 
-  if (dlclose(coreclrLib) != 0)
-  {
-    _ERR("libcoreclr.so close failed");
-    return 1;
-  }
+void LaunchpadAdapterImpl::OnCreate()
+{
+}
 
-  return 0;
+void LaunchpadAdapterImpl::OnLaunch()
+{
 }
 
-int main(int argc, char *argv[])
+void LaunchpadAdapterImpl::OnTerminate()
 {
-#ifdef NO_TIZEN
-  const char *_deviceapi_directory = getenv("DeviceAPIDirectory");
-  const char *_runtime_directory = getenv("RuntimeDirectory");
-  const char *_launcher_assembly = getenv("LauncherAssembly");
-  if (_deviceapi_directory != nullptr)
-    DeviceAPIDirectory = _deviceapi_directory;
-  if (_runtime_directory != nullptr)
-    RuntimeDirectory = _runtime_directory;
-  if (_launcher_assembly != nullptr)
-    LauncherAssembly = _launcher_assembly;
-#endif
-  _DBG("launcher started");
-  return RunLauncherDll(argc, argv);
 }
+
+
+}  // namespace runtime
+}  // namespace tizen
diff --git a/NativeLauncher/src/launcher.h b/NativeLauncher/src/launcher.h
deleted file mode 100644 (file)
index 4800ddf..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-#include <string>
-#include <vector>
-
-namespace dotnet {
-namespace runtime {
-
-typedef int (*coreclr_initialize_ptr)(
-    const char* exePath,
-    const char* appDomainFriendlyName,
-    int propertyCount,
-    const char** propertyKeys,
-    const char** propertyValues,
-    void** hostHandle,
-    unsigned int* domainId);
-
-typedef int (*coreclr_execute_assembly_ptr)(
-    void* hostHandle,
-    unsigned int domainId,
-    int argc,
-    const char** argv,
-    const char* managedAssemblyPath,
-    unsigned int* exitCode);
-
-typedef int (*coreclr_shutdown_ptr)(
-    void* hostHandle,
-    unsigned int domainId);
-
-typedef int (*coreclr_create_delegate_ptr)(
-    void* hostHandle,
-    unsigned int domainId,
-    const char* entryPointAssemblyName,
-    const char* entryPointTypeName,
-    const char* entryPointMethodName,
-    void** delegate);
-
-typedef bool (*AssemblyManager_Initialize)(
-    const char* searchableDirectories,
-    const char* preloadDllPaths);
-
-typedef void (*AssemblyManager_AddAssemblyDir)(const char* dir); 
-typedef void (*AssemblyManager_RemoveAssemblyDir)(const char* dir); 
-
-typedef void (*AssemblyManager_Execute)(const char* dllPath);
-typedef void (*AssemblyManager_Finish)(void);
-
-using std::string;
-using std::vector;
-
-class Launcher
-{
-  public:
-    Launcher();
-    ~Launcher();
-    void Initialize();
-
-  private:
-    coreclr_initialize_ptr initializeCoreCLR;
-//    coreclr_execute_assembly_ptr executeAssembly;
-    coreclr_shutdown_ptr shutdownCoreCLR;
-    coreclr_create_delegate_ptr createDelegate;
-
-    string TrustedPlatformAssemblies;
-    string NativeDllSearchDirectories;
-    string AppDomainCompatSwitch;
-
-    void *coreclrLib;
-
-    AssemblyManager_Initialize assemblyManagerInitialize;
-    AssemblyManager_Execute assemblyManagerExecute;
-    AssemblyManager_Finish assemblyManagerFinish;
-    AssemblyManager_AddAssemblyDir assemblyManagerAddDir;
-    AssemblyManager_RemoveAssemblyDir assemblyManagerRemoveDir;
-
-    bool initialized;
-};
-
-}  // namespace runtime
-}  // namespace dotnet
diff --git a/NativeLauncher/src/tini.hpp b/NativeLauncher/src/tini.hpp
deleted file mode 100644 (file)
index fac3424..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-#include <string>
-#include <map>
-#include <vector>
-#include <sstream>
-#include <algorithm> 
-#include <functional> 
-
-namespace tini
-{
-
-const std::string global = "___GLOBAL";
-
-inline void ltrim(std::string& s)
-{
-  s.erase(s.begin(), std::find_if(s.begin(), s.end(),
-        std::not1(std::ptr_fun<int, int>(std::isspace))));
-}
-
-inline void rtrim(std::string& s)
-{
-  s.erase(std::find_if(s.rbegin(), s.rend(),
-        std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
-}
-
-inline void trim(std::string& s)
-{
-  ltrim(s);
-  rtrim(s);
-}
-
-inline int find_first_nonescaped(const std::string& str, char ch)
-{
-  if (!str.empty())
-  {
-    if (str[0] == ch) return 0;
-    for (size_t i=1; i<str.length(); i++)
-    {
-      if (str[i] == ch && str[i-1] != '\\')
-        return i;
-    }
-  }
-  return -1;
-}
-
-inline std::string uncomment(const std::string& str)
-{
-  int comment_start = find_first_nonescaped(str, '#');
-  if (comment_start < 0) return str;
-  return str.substr(0, comment_start);
-}
-
-inline bool get_header(const std::string& str, std::string& header)
-{
-  if (str.length() < 2 || str.front() != '[' || str.back() != ']') return false;
-  std::string expected = std::string(str.begin()+1, str.end()-1);
-  trim(expected);
-  if (expected.compare(header) != 0)
-  {
-    header = expected;
-    return true;
-  }
-  return false;
-}
-
-inline std::pair<std::string, std::string> get_pair(const std::string& str)
-{
-  std::string key, value;
-  std::string::size_type eq_pos = str.find('=');
-  if (eq_pos == std::string::npos)
-  {
-    key = str;
-  }
-  else
-  {
-    key = str.substr(0, eq_pos);
-    value = str.substr(eq_pos+1);
-    trim(value);
-  }
-  trim(key);
-  return std::pair<std::string, std::string>(key, value);
-}
-
-class ini
-{
-  public:
-    using pairs = std::map<std::string, std::string>;
-    ini()
-    {
-    }
-    ini(const std::string& str)
-    {
-      std::istringstream input(str);
-      init(input);
-    }
-    ini(std::istream &input)
-    {
-      init(input);
-    }
-    inline void init (std::istream &input)
-    {
-      std::string line;
-      std::string title(global);
-      while (std::getline(input, line))
-      {
-        line = uncomment(line);
-        if (line.empty()) continue;
-        trim(line);
-        if (get_header(line, title) && groups.find(title) == groups.end())
-        {
-          groups[title] = std::map<std::string, std::string>();
-          continue;
-        }
-
-        auto pair = get_pair(line);
-        groups[title][pair.first] = pair.second;
-      }
-    }
-    std::string to_string() const
-    {
-      std::stringstream str_out;
-      auto gpair = groups.find(global);
-      if (gpair != groups.end())
-      {
-        for (auto &pair : gpair->second)
-        {
-          str_out << pair.first << " = " << pair.second << std::endl;
-        }
-      }
-      for (auto &group : groups)
-      {
-        auto &title = group.first;
-        if (title == global) continue;
-        auto &pairs = group.second;
-        str_out << '[' << title << ']' << std::endl;
-        for (auto &pair : pairs)
-        {
-          str_out << pair.first << " = " << pair.second << std::endl;
-        }
-      }
-
-      return str_out.str();
-    }
-
-    pairs& operator [](const std::string& group_name)
-    {
-      if (groups.find(group_name) == groups.end())
-      {
-        groups[group_name] = pairs();
-      }
-      return groups[group_name];
-    }
-
-    std::map<std::string, pairs> groups;
-};
-
-std::ostream& operator << (std::ostream& os, const ini& rhs)
-{
-  os << rhs.to_string();
-  return os;
-}
-
-}  // namespace tini
diff --git a/NativeLauncher/src/utils.cc b/NativeLauncher/src/utils.cc
new file mode 100644 (file)
index 0000000..776fd9f
--- /dev/null
@@ -0,0 +1,211 @@
+
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <limits.h>
+#include <strings.h>
+
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+#include <set>
+#include <vector>
+#include <iterator>
+#include <sstream>
+
+#include "utils.h"
+
+std::string ReadSelfPath()
+{
+  char buff[PATH_MAX];
+  ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
+  if (len != -1) {
+    buff[len] = '\0';
+    return std::string(buff);
+  }
+
+  return "";
+}
+
+std::string ConcatPath(const std::string& path1, const std::string& path2)
+{
+  std::string path(path1);
+  if (path.back() == PATH_SEPARATOR)
+  {
+    path.append(path2);
+  }
+  else
+  {
+    path += PATH_SEPARATOR;
+    path.append(path2);
+  }
+
+  return path;
+}
+
+void AppendPath(std::string& path1, const std::string& path2)
+{
+  if (path1.back() == PATH_SEPARATOR)
+  {
+    path1.append(path2);
+  }
+  else
+  {
+    path1 += PATH_SEPARATOR;
+    path1.append(path2);
+  }
+}
+
+std::string AbsolutePath(const std::string& path)
+{
+  std::string absPath;
+
+  char realPath[PATH_MAX];
+  if (realpath(path.c_str(), realPath) != nullptr && realPath[0] != '\0')
+  {
+    absPath.assign(realPath);
+  }
+
+  return absPath;
+}
+
+std::string Basename(const std::string& path)
+{
+  auto pos = path.find_last_of(PATH_SEPARATOR);
+  if (pos != std::string::npos)
+  {
+    return path.substr(0, pos);
+  }
+  else
+  {
+    return std::string(".");
+  }
+  return path;
+}
+
+bool EndWithIgnoreCase(const std::string& str1, const std::string& str2, std::string& filename)
+{
+  std::string::size_type len1 = str1.length();
+  std::string::size_type len2 = str2.length();
+  if (len2 > len1) return false;
+
+  int i = 0;
+  bool result = std::all_of(str1.cend() - len2, str1.end(),
+        [&i, &str2] (char x) {
+          return std::tolower(x) == std::tolower(str2[i++]);
+        });
+  if (result)
+  {
+    filename = str1.substr(0, len1 - len2);
+  }
+  return result;
+}
+
+bool FileNotExist(const std::string& path)
+{
+  struct stat sb;
+  return (stat(path.c_str(), &sb) != 0) || !S_ISREG(sb.st_mode);
+}
+
+static bool ExtCheckAndGetFileNameIfExist(const std::string&  dir, const std::string& ext, struct dirent* entry, std::string& filename)
+{
+  std::string fname(entry->d_name);
+  if (fname.length() < ext.length() ||
+      fname.compare(fname.length() - ext.length(), ext.length(), ext) != 0)
+  {
+    return false;
+  }
+  std::string fullname = ConcatPath(dir, entry->d_name);
+  switch (entry->d_type)
+  {
+    case DT_REG: break;
+    case DT_LNK:
+    case DT_UNKNOWN:
+      if (FileNotExist(fullname))
+      {
+        return false;
+      }
+    default:
+      return false;
+  }
+
+  filename = fullname;
+
+  return true;
+}
+
+std::string StripNIDLL(const std::string& path)
+{
+  std::string npath(path);
+  if (path.size() < 5) return npath;
+  if (strncasecmp(path.c_str() + path.size() - 4, ".dll", 4))
+  {
+    npath = path.substr(0, path.size()-4);
+  }else if (strncasecmp(path.c_str() + path.size() - 4, ".exe", 4))
+  {
+    npath = path.substr(0, path.size()-4);
+  }
+  if (strncasecmp(npath.c_str() + npath.size() - 3, ".ni", 3))
+  {
+    return npath.substr(0, npath.size()-3);
+  }
+  return npath;
+}
+
+std::string JoinStrings(const std::vector<std::string>& strings, const char* const delimeter)
+{
+  switch (strings.size())
+  {
+    case 0:
+      return "";
+    case 1:
+      return strings[0];
+    default:
+      std::ostringstream os; 
+      std::copy(strings.begin(), strings.end()-1, std::ostream_iterator<std::string>(os, delimeter));
+      os << *strings.rbegin();
+      return os.str();
+  }
+}
+
+void AssembliesInDirectory(const std::vector<std::string>& directories, std::string& tpaList)
+{
+  static const std::string tpaExtensions[] =
+  {".ni.dll", ".dll", ".ni.exe", ".exe"};
+
+  std::set<std::string> addedAssemblies;
+
+  DIR* dir = nullptr;
+  struct dirent* entry = nullptr;
+
+  for (auto directory : directories)
+  {
+    dir = opendir(directory.c_str());
+    if (dir == nullptr)
+    {
+      continue;
+    }
+
+    for (auto ext : tpaExtensions)
+    {
+      while ((entry = readdir(dir)) != nullptr)
+      {
+        std::string fullname;
+        if (ExtCheckAndGetFileNameIfExist(directory.c_str(), ext, entry, fullname))
+        {
+          std::string filename = StripNIDLL(fullname);
+          if (addedAssemblies.find(filename) == addedAssemblies.end())
+          {
+            addedAssemblies.insert(filename);
+            tpaList += fullname + ':';
+          }
+        }
+      }
+      rewinddir(dir);
+    }
+    closedir(dir);
+  }
+  if (tpaList.back() == ':')
+    tpaList.pop_back();
+
+}
index 0eeaffa..6a13648 100644 (file)
@@ -3,11 +3,29 @@ using System.IO;
 using System.Reflection;
 using System.Runtime.Loader;
 using System.Linq;
+using System.Runtime.InteropServices;
 
 namespace Tizen.Runtime
 {
     public static class AssemblyManager
     {
+        public static bool Launch(
+                [In] string path,
+                [In] int argc,
+                [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]
+                [In] string[] argv)
+        {
+            Console.WriteLine($"path : {path}");
+            Console.WriteLine($"argc : {argc}");
+            for (int i=0; i<argc; i++)
+            {
+                Console.WriteLine($"argv[{i}] : " + argv[i]);
+            }
+            Console.WriteLine();
+
+            return true;
+        }
+
         public static int Prepared(IntPtr data)
         {
             try
@@ -82,11 +100,14 @@ namespace Tizen.Runtime
         {
             try
             {
+                /*
                 preparedCallback = Prepared;
                 requestedCallback = Requested;
                 executedCallback = Executed;
                 Interop.register_launching_callback(preparedCallback, requestedCallback, executedCallback, IntPtr.Zero);
                 Interop.wait_for_launching(args.Length, args);
+                */
+                Console.WriteLine("HelloWorld!!");
             }
             catch(Exception e)
             {
index d6d4ab4..c82b091 100644 (file)
@@ -60,7 +60,7 @@ cmake \
        -DVERSION=%{version} \
        NativeLauncher
 
-make %{?jobs:-j%jobs}
+make %{?jobs:-j%jobs} VERBOSE=1
 
 xbuild \
        /p:Configuration=%{_buildmode} \
@@ -77,5 +77,4 @@ install -p -m 644 Tizen.Runtime/bin/Tizen.Runtime.exe %{buildroot}%{_bindir}
 %manifest dotnet-launcher.manifest
 %{_loaderdir}/dotnet.loader
 %caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/dotnet-launcher
-%caps(cap_mac_admin,cap_setgid=ei) %{_libdir}/libdnclauncher.so
 %caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/Tizen.Runtime.exe
index a013029..bcd8337 100755 (executable)
@@ -14,9 +14,10 @@ PreloadPath=`readlink -e ./preloads`
 
 mkdir build
 cd build
-cmake -DCMAKE_BUILD_TYPE=Debug -DNO_TIZEN=1 -DLAUNCHER_ASSEMBLY_PATH=Tizen.Runtime.exe -DDEVICE_API_DIR=$TizenDeviceAPIDir -DRUNTIME_DIR=$RuntimeDir ../NativeLauncher/
-make
-xbuild /t:Clean ../Tizen.Runtime/Tizen.Runtime.csproj
+#xbuild /t:Clean ../Tizen.Runtime/Tizen.Runtime.csproj
 #xbuild /verbosity:diagnostic /p:CLOG=1 /p:ExternalCscPath=/home/idkiller/work/runtime/roslyn/Binaries/Debug/csccore/csc.exe /p:LauncherConfigPath=$LauncherConfigPath /p:CoreFXRefPath=$CoreFXRefPath /p:TizenDeviceAPIPath=$TizenDeviceAPIPath ../Tizen.Runtime/Tizen.Runtime.csproj
-xbuild /p:CLOG=1 /p:ExternalCscDir=$RoslynCscDir /p:ExternalCscExe=$RoslynCscExe /p:LauncherConfigPath=$LauncherConfigPath /p:CoreFXRefPath=$CoreFXRefPath /p:TizenDeviceAPIPath=$TizenDeviceAPIPath /p:PreloadPath=$PreloadPath ../Tizen.Runtime/Tizen.Runtime.csproj
-cp ../Tizen.Runtime/bin/Tizen.Runtime.* .
+#xbuild /p:CLOG=1 /p:ExternalCscDir=$RoslynCscDir /p:ExternalCscExe=$RoslynCscExe /p:LauncherConfigPath=$LauncherConfigPath /p:CoreFXRefPath=$CoreFXRefPath /p:TizenDeviceAPIPath=$TizenDeviceAPIPath /p:PreloadPath=$PreloadPath ../Tizen.Runtime/Tizen.Runtime.csproj
+#cp ../Tizen.Runtime/bin/Tizen.Runtime.* .
+
+cmake -DCMAKE_BUILD_TYPE=Debug -DNO_TIZEN=1 -DLAUNCHER_ASSEMBLY_PATH=Tizen.Runtime.exe -DDEVICE_API_DIR=$TizenDeviceAPIDir -DRUNTIME_DIR=$RuntimeDir ../NativeLauncher/
+make -j16