Add managed launcher part
authorpius.lee <pius.lee@samsung.com>
Fri, 19 Aug 2016 04:57:46 +0000 (13:57 +0900)
committerpius.lee <pius.lee@samsung.com>
Fri, 19 Aug 2016 04:57:46 +0000 (13:57 +0900)
Move native launcher part from src to NativeLauncher
Add Tizen.Runtime.dll to Tizen.Runtime
Tizen.Runtime can preload and launching another assembly

28 files changed:
CMakeLists.txt [deleted file]
NativeLauncher/CMakeLists.txt [new file with mode: 0644]
NativeLauncher/dotnet-launcher.ini [new file with mode: 0644]
NativeLauncher/dotnet.loader [new file with mode: 0644]
NativeLauncher/src/environment.h [new file with mode: 0644]
NativeLauncher/src/launcher.cc [new file with mode: 0644]
NativeLauncher/src/launcher.h [new file with mode: 0644]
NativeLauncher/src/log.h [new file with mode: 0644]
NativeLauncher/src/tini.hpp [new file with mode: 0644]
NativeLauncher/src/waiter.cc [new file with mode: 0644]
NativeLauncher/src/waiter.h [new file with mode: 0644]
Tizen.Runtime/Tizen.CoreFX.Ref.Targets [new file with mode: 0644]
Tizen.Runtime/Tizen.Runtime.csproj [new file with mode: 0644]
Tizen.Runtime/Tizen.Runtime.snk [new file with mode: 0644]
Tizen.Runtime/Tizen.Runtime/AssemblyLoader.cs [new file with mode: 0644]
Tizen.Runtime/Tizen.Runtime/AssemblyManager.cs [new file with mode: 0644]
Tizen.Runtime/Tizen.Runtime/Log.cs [new file with mode: 0644]
Tizen.Runtime/Tizen.Runtime/test.cs [new file with mode: 0644]
packaging/dotnet-launcher.ini [deleted file]
packaging/dotnet-launcher.spec
packaging/dotnet.loader [deleted file]
src/environment.h [deleted file]
src/launcher.cc [deleted file]
src/launcher.h [deleted file]
src/log.h [deleted file]
src/tini.hpp [deleted file]
src/waiter.cc [deleted file]
src/waiter.h [deleted file]

diff --git a/CMakeLists.txt b/CMakeLists.txt
deleted file mode 100644 (file)
index 0d49eba..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-PROJECT("dotnet-launcher")
-
-MESSAGE("CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
-
-IF(DEFINED NO_TIZEN)
-       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DNO_TIZEN")
-ELSE(DEFINED NO_TIZEN)
-       INCLUDE(FindPkgConfig)
-       PKG_CHECK_MODULES(${PROJECT_NAME} REQUIRED aul dlog ecore bundle dlog launchpad)
-ENDIF(DEFINED NO_TIZEN)
-
-FOREACH(flag ${${PROJECT_NAME}_CFLAGS})
-       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
-ENDFOREACH(flag)
-
-IF(DEFINED LAUNCHER_PATH)
-       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DLAUNCHER_PATH=${LAUNCHER_PATH}")
-ENDIF(DEFINED LAUNCHER_PATH)
-
-
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -std=c++11")
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,-zdefs" )
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fPIE")
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fdata-sections -ffunction-sections -Wl,--gc-sections")
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -D_FILE_OFFSET_BITS=64")
-#SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DLAUNCHING_TIME_MEASURE")
-
-SET(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
-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
-       src/launcher.cc
-       src/waiter.cc
-)
-
-ADD_EXECUTABLE(${PROJECT_NAME} ${${PROJECT_NAME}_SOURCE_FILES})
-
-IF(NOT DEFINED NO_TIZEN)
-       TARGET_LINK_LIBRARIES(${PROJECT_NAME} aul)
-ENDIF(NOT DEFINED NO_TIZEN)
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl")
-
-SET_TARGET_PROPERTIES(${PROJECT_NAME}
-       PROPERTIES SKIP_BUILD_RPATH TRUE
-       ) # remove rpath option that is automatically generated by cmake.
-
-IF(NOT DEFINED NO_TIZEN)
-       INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${BINDIR})
-       INSTALL(FILES packaging/dotnet.loader DESTINATION ${LOADERDIR})
-       INSTALL(FILES packaging/dotnet-launcher.ini DESTINATION ${CONFIGDIR})
-ENDIF(NOT DEFINED NO_TIZEN)
diff --git a/NativeLauncher/CMakeLists.txt b/NativeLauncher/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e55c12c
--- /dev/null
@@ -0,0 +1,55 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT("dotnet-launcher")
+
+MESSAGE("CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
+
+IF(DEFINED NO_TIZEN)
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DNO_TIZEN")
+ELSE(DEFINED NO_TIZEN)
+       INCLUDE(FindPkgConfig)
+       PKG_CHECK_MODULES(${PROJECT_NAME} REQUIRED aul dlog ecore bundle dlog launchpad)
+ENDIF(DEFINED NO_TIZEN)
+
+FOREACH(flag ${${PROJECT_NAME}_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+IF(DEFINED LAUNCHER_PATH)
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DLAUNCHER_PATH=${LAUNCHER_PATH}")
+ENDIF(DEFINED LAUNCHER_PATH)
+
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -std=c++11")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,-zdefs" )
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fPIE")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fdata-sections -ffunction-sections -Wl,--gc-sections")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -D_FILE_OFFSET_BITS=64")
+#SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DLAUNCHING_TIME_MEASURE")
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+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
+       src/launcher.cc
+       src/waiter.cc
+)
+
+ADD_EXECUTABLE(${PROJECT_NAME} ${${PROJECT_NAME}_SOURCE_FILES})
+
+IF(NOT DEFINED NO_TIZEN)
+       TARGET_LINK_LIBRARIES(${PROJECT_NAME} aul)
+ENDIF(NOT DEFINED NO_TIZEN)
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl")
+
+SET_TARGET_PROPERTIES(${PROJECT_NAME}
+       PROPERTIES SKIP_BUILD_RPATH TRUE
+       ) # remove rpath option that is automatically generated by cmake.
+
+IF(NOT DEFINED NO_TIZEN)
+       INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${BINDIR})
+       INSTALL(FILES dotnet.loader DESTINATION ${LOADERDIR})
+       INSTALL(FILES dotnet-launcher.ini DESTINATION ${CONFIGDIR})
+ENDIF(NOT DEFINED NO_TIZEN)
diff --git a/NativeLauncher/dotnet-launcher.ini b/NativeLauncher/dotnet-launcher.ini
new file mode 100644 (file)
index 0000000..9d4809c
--- /dev/null
@@ -0,0 +1,5 @@
+[dotnet]
+libcoreclr = libcoreclr.so
+coreclr_dir = /opt/usr/share/dotnet/shared/Microsoft.NETCore.App/1.0.0
+tpa_dirs = /opt/usr/share/dotnet/shared/Microsoft.NETCore.App/1.0.0:/usr/share/assembly
+native_so_search_dirs = /opt/usr/share/dotnet/shared/Microsoft.NETCore.App/1.0.0:/usr/share/assembly
diff --git a/NativeLauncher/dotnet.loader b/NativeLauncher/dotnet.loader
new file mode 100644 (file)
index 0000000..67094b9
--- /dev/null
@@ -0,0 +1,6 @@
+[LOADER]
+NAME    dotnet-launcher
+EXE     /usr/bin/dotnet-launcher
+APP_TYPE        dotnet
+DETECTION_METHOD        TIMEOUT|DEMAND
+TIMEOUT         5000
diff --git a/NativeLauncher/src/environment.h b/NativeLauncher/src/environment.h
new file mode 100644 (file)
index 0000000..6e4e57b
--- /dev/null
@@ -0,0 +1,12 @@
+#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__
diff --git a/NativeLauncher/src/launcher.cc b/NativeLauncher/src/launcher.cc
new file mode 100644 (file)
index 0000000..fcd1555
--- /dev/null
@@ -0,0 +1,414 @@
+#include <dlfcn.h>
+
+#ifdef LAUNCHING_TIME_MEASURE
+#include <ctime>
+#endif
+
+#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 "environment.h"
+#include "waiter.h"
+#include "log.h"
+
+#include "tini.hpp"
+
+#include "launcher.h"
+
+namespace dotnet {
+namespace runtime {
+
+#ifdef LAUNCHER_PATH
+#define __STR(x) #x
+#define __XSTR(x) __STR(x)
+#define LAUNCHER_CONFIG __XSTR(LAUNCHER_PATH)
+#else
+#define LAUNCHER_CONFIG "/etc/dotnet-launcher.ini"
+#endif
+static const std::string LauncherConfig(LAUNCHER_CONFIG);
+#ifdef LAUNCHER_PATH
+#undef __STR
+#undef __XSTR
+#undef LAUNCHER_CONFIG
+#undef LAUNCHER_PATH
+#endif
+
+#ifndef PATH_SEPARATOR
+#define PATH_SEPARATOR '/'
+#endif
+
+static 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;
+}
+static void AppendPath(std::string& path1, const std::string& path2)
+{
+  if (path1.back() == PATH_SEPARATOR)
+  {
+    path1.append(path2);
+  }
+  else
+  {
+    path1 += PATH_SEPARATOR;
+    path1.append(path2);
+  }
+}
+
+static 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;
+}
+
+static 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);
+  }
+  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)
+  {
+    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);
+
+  if (dir == nullptr)
+  {
+    _ERR("can not open directory : %s", directory);
+    return std::string();
+  }
+
+  std::set<std::string> addedAssemblies;
+
+  struct dirent *entry;
+
+  int tpaCount = sizeof(tpaExtensions) / sizeof(tpaExtensions[0]);
+  for (int i=0; i<tpaCount; i++)
+  {
+    const std::string& ext = tpaExtensions[i];
+    bool isNativeExt = tpaExtensions_ni[i];
+
+    while ((entry = readdir(dir)) != nullptr)
+    {
+      switch (entry->d_type)
+      {
+        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:
+          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 + ':';
+      }
+    }
+    rewinddir(dir);
+  }
+
+  closedir(dir);
+  return tpaList;
+}
+
+Launcher::Launcher()
+{
+}
+
+Launcher::~Launcher()
+{
+}
+
+void Launcher::Initialize()
+{
+#ifdef LAUNCHING_TIME_MEASURE
+  std::clock_t start = std::clock();
+#endif
+
+  std::ifstream iniStream(LauncherConfig);
+  std::stringstream iniString;
+  iniString << iniStream.rdbuf();
+  tini::ini launcherIni(iniString);
+
+  _DBG("config file [%s]", LauncherConfig.c_str());
+  _DBG("%s", launcherIni.to_string().c_str());
+
+  auto &dotnet = launcherIni["dotnet"];
+  if (dotnet.find("libcoreclr") == dotnet.end())
+    dotnet["libcoreclr"] = "libcoreclr.so";
+  if (dotnet.find("coreclr_dir") == dotnet.end())
+    dotnet["coreclr_dir"] = "/usr/share/dotnet";
+  if (dotnet.find("tpa_dir") == dotnet.end())
+    dotnet["tpa_dir"] = dotnet["coreclr_dir"] + ":" + "/usr/share/assemblies";
+  if (dotnet.find("native_so_search_dirs") == dotnet.end())
+    dotnet["native_so_search_dirs"] = dotnet["tpa_dir"];
+
+  _DBG("libcoreclr : %s", dotnet["libcoreclr"].c_str());
+  _DBG("coreclr_dir : %s", dotnet["coreclr_dir"].c_str());
+  _DBG("tpa_dir : %s", dotnet["tpa_dir"].c_str());
+  _DBG("native_so_search_dirs : %s", dotnet["native_so_search_dirs"].c_str());
+
+  std::string libcoreclr = dotnet["coreclr_dir"] + "/" + dotnet["libcoreclr"];
+  std::string tpaDirs = dotnet["tpa_dirs"];
+  std::string nativeSoSearchDirs = dotnet["native_so_search_dirs"];
+
+  _DBG("libcoreclr.so : [%s]", libcoreclr.c_str());
+
+#ifdef LAUNCHING_TIME_MEASURE
+  std::clock_t config_read_time = std::clock();
+  _DBG("Reading Config file... : %Lf ms ", (config_read_time - start) / (double)(CLOCKS_PER_SEC / 1000));
+#endif
+
+  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;
+  }
+
+  initializeCoreCLR = (coreclr_initialize_ptr)dlsym(coreclrLib, "coreclr_initialize");
+  executeAssembly = (coreclr_execute_assembly_ptr)dlsym(coreclrLib, "coreclr_execute_assembly");
+  shutdownCoreCLR = (coreclr_shutdown_ptr)dlsym(coreclrLib, "coreclr_shutdown");
+
+  if (initializeCoreCLR == nullptr)
+  {
+    _ERR("coreclr_initialize not found in the libcoreclr.so");
+  }
+  else if (executeAssembly == nullptr)
+  {
+    _ERR("coreclr_execute_assembly_ptr not found in the libcoreclr.so");
+  }
+  else if (shutdownCoreCLR == nullptr)
+  {
+    _ERR("coreclr_shutdown_ptr not found in the libcoreclr.so");
+  }
+  else
+  {
+    std::istringstream f(tpaDirs);
+    std::string s;
+    while (std::getline(f, s, ':'))
+    {
+      TrustedPlatformAssemblies += AssembliesInDirectory(s.c_str());
+    }
+    NativeDllSearchDirectories = nativeSoSearchDirs; 
+    AppDomainCompatSwitch = "UseLatestBehaviorWhenTFMNotSpecified";
+  }
+
+#ifdef LAUNCHING_TIME_MEASURE
+  std::clock_t dlopen_time = std::clock();
+  _DBG("dlopen and dlsym time... : %Lf ms ", (dlopen_time - config_read_time) / (double)(CLOCKS_PER_SEC / 1000));
+  _DBG("initialize time... : %Lf ms ", (dlopen_time - start) / (double)(CLOCKS_PER_SEC / 1000));
+#endif
+
+}
+
+void Launcher::Launch(const string& exe_path, const string& app_root, int argc, char *argv[])
+{
+  std::string bin_path = Basename(AbsolutePath(exe_path));
+  std::string lib_path = ConcatPath(AbsolutePath(app_root), "lib");
+  std::string app_path = bin_path + ":" + lib_path;
+  std::string app_ni_path = app_path;
+  std::string nativeDllSearchDirectories = NativeDllSearchDirectories + app_path;
+
+  const char *propertyKeys[] =
+  {
+    "TRUSTED_PLATFORM_ASSEMBLIES",
+    "APP_PATHS",
+    "APP_NI_PATHS",
+    "NATIVE_DLL_SEARCH_DIRECTORIES",
+    "AppDomainCompatSwitch"
+  };
+
+  const char *propertyValues[] =
+  {
+    TrustedPlatformAssemblies.c_str(),
+    app_path.c_str(),
+    app_ni_path.c_str(),
+    nativeDllSearchDirectories.c_str(),
+    AppDomainCompatSwitch.c_str()
+  };
+
+  //_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]);
+
+  void* hostHandle;
+  unsigned int domainId;
+
+  _DBG("before initialize coreclr");
+
+#ifdef LAUNCHING_TIME_MEASURE
+  std::clock_t start = std::clock();
+#endif
+  int st = initializeCoreCLR(exe_path.c_str(),
+      "tizen_dotnet_launcher",
+      sizeof(propertyKeys) / sizeof(propertyKeys[0]),
+      propertyKeys,
+      propertyValues,
+      &hostHandle,
+      &domainId);
+
+  _DBG("after initialize coreclr");
+#ifdef LAUNCHING_TIME_MEASURE
+  std::clock_t initialize_coreclr_time = std::clock();
+  _DBG("call coreclr_initialize ... : %Lf ms ", (initialize_coreclr_time - start) / (double)(CLOCKS_PER_SEC / 1000));
+#endif
+  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");
+  }
+  else
+  {
+    unsigned int exitCode;
+    const char** argvc = const_cast<const char**>(argv);
+    st = executeAssembly(hostHandle, domainId, argc, argvc, exe_path.c_str(), &exitCode);
+    _DBG("after execute coreclr");
+    if (st < 0)
+    {
+      // execute coreclr fail
+      _ERR("execute core clr fail! (0x%08x / %d)", st, exitCode);
+    }
+    st = shutdownCoreCLR(hostHandle, domainId);
+    if (st < 0)
+    {
+      // shutdown fail
+      _ERR("shutdown core clr fail! (0x%08x)", st);
+    }
+#ifdef LAUNCHING_TIME_MEASURE
+    std::clock_t execute_assembly_time = std::clock();
+    _DBG("call execute_assembly_time ... : %Lf ms ", (execute_assembly_time - initialize_coreclr_time) / (double)(CLOCKS_PER_SEC / 1000));
+#endif
+  }
+  if (dlclose(coreclrLib) != 0)
+  {
+    _ERR("libcoreclr.so close failed");
+  }
+#ifdef LAUNCHING_TIME_MEASURE
+    std::clock_t after_launching_time = std::clock();
+    _DBG("launching end time ... : %Lf ms ", (after_launching_time - start) / (double)(CLOCKS_PER_SEC / 1000));
+#endif
+}
+
+}  // namespace runtime
+}  // namespace dotnet
+
+using dotnet::runtime::Launcher;
+using dotnet::runtime::Waiter;
+
+int main(int argc, char *argv[])
+{
+  _DBG("launcher started");
+
+  for (int i=0; i<argc; i++)
+  {
+    _DBG("argv[%d](%d) : [%s]", i, strlen(argv[i]), argv[i]);
+  }
+
+  std::unique_ptr<Launcher> launcher(new Launcher());
+  auto on_prepare = [&launcher]()
+  {
+    launcher->Initialize();
+  };
+  auto on_requested = [&launcher]()
+  {
+  };
+  auto on_executed = [&launcher](const std::string& path, const std::string& app_root, int argc, char *argv[])
+  {
+    _DBG("EXECUTE %s", path.c_str());
+    launcher->Launch(path, app_root, argc, argv);
+  };
+  std::unique_ptr<Waiter> waiter(new Waiter(on_prepare, on_requested, on_executed));
+  waiter->WaitToLaunching(argc, argv);
+}
diff --git a/NativeLauncher/src/launcher.h b/NativeLauncher/src/launcher.h
new file mode 100644 (file)
index 0000000..acba908
--- /dev/null
@@ -0,0 +1,52 @@
+#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);
+
+using std::string;
+using std::vector;
+
+class Launcher
+{
+  public:
+    Launcher();
+    ~Launcher();
+    void Initialize();
+    void Launch(const string& exe_path, const string& app_root, int argc, char *argv[]);
+
+  private:
+    coreclr_initialize_ptr initializeCoreCLR;
+    coreclr_execute_assembly_ptr executeAssembly;
+    coreclr_shutdown_ptr shutdownCoreCLR;
+
+    string TrustedPlatformAssemblies;
+    string NativeDllSearchDirectories;
+    string AppDomainCompatSwitch;
+
+    void *coreclrLib;
+};
+
+}  // namespace runtime
+}  // namespace dotnet
diff --git a/NativeLauncher/src/log.h b/NativeLauncher/src/log.h
new file mode 100644 (file)
index 0000000..59f2dc9
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef __LOG_H__
+#define __LOG_H__
+
+#ifndef NO_TIZEN
+#include <dlog.h>
+#else
+#include <stdio.h>
+#define LOGE(fmt, args...) printf(fmt, ##args)
+#define LOGD(fmt, args...) printf(fmt, ##args)
+#define LOGI(fmt, args...) printf(fmt, ##args)
+#endif
+
+#ifdef  LOG_TAG
+#undef  LOG_TAG
+#endif
+#define LOG_TAG "NETCORE_LAUNCHER"
+
+#ifndef _ERR
+#define _ERR(fmt, args...) LOGE(fmt "\n", ##args)
+#endif
+
+#ifndef _DBG
+#define _DBG(fmt, args...) LOGD(fmt "\n", ##args)
+#endif
+
+#ifndef _INFO
+#define _INFO(fmt, args...) LOGI(fmt "\n", ##args)
+#endif
+
+#endif /* __LOG_H__ */
diff --git a/NativeLauncher/src/tini.hpp b/NativeLauncher/src/tini.hpp
new file mode 100644 (file)
index 0000000..fac3424
--- /dev/null
@@ -0,0 +1,162 @@
+#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/waiter.cc b/NativeLauncher/src/waiter.cc
new file mode 100644 (file)
index 0000000..6f83482
--- /dev/null
@@ -0,0 +1,222 @@
+
+#include <poll.h>
+
+#ifndef NO_TIZEN
+#include <launchpad.h>
+#include <aul.h>
+#endif
+
+#include <memory>
+#include <vector>
+#include <map>
+#include <poll.h>
+
+#include <iostream>
+
+#include "waiter.h"
+#include "log.h"
+
+namespace dotnet {
+namespace runtime {
+
+struct FdHandler
+{
+  pollfd *info;
+  Receiver receiver;
+};
+
+static volatile bool Waiting_;
+static std::vector<pollfd> Fdlist_;
+static std::map<int, FdHandler> Handlers_;
+static Waiter::AppInfo AppInfo_;
+
+void Waiter::OnPrepare()
+{
+  // preload the libraries.
+  if (prepare_ != nullptr)
+    prepare_();
+}
+
+void Waiter::OnLaunchRequested(const AppInfo& info)
+{
+  // do some job on user id is still system
+}
+
+void Waiter::OnWaiting()
+{
+  // Start the loop
+  Waiting_ = true;
+
+  _DBG("start polling...");
+  while (Waiting_)
+  {
+    if (poll(Fdlist_.data(), Fdlist_.size(), -1) < 0)
+      continue;
+
+    for (auto &p : Fdlist_)
+    {
+      if ( (p.revents | POLLIN) != 0 )
+        Handlers_[p.fd].receiver(p.fd);
+    }
+  }
+  _DBG("end polling...");
+}
+
+void Waiter::Stop()
+{
+  // Stop the loop
+
+  Waiting_ = false;
+}
+
+
+void Waiter::RegisterFd(int fd, Receiver receiver)
+{
+  // register fd should be caught in event loop
+
+  _DBG("Register fd %d", fd);
+
+  pollfd info;
+  info.fd = fd;
+  info.events = POLLIN;
+  info.revents = 0;
+
+  FdHandler handler;
+  Fdlist_.push_back(info);
+  handler.info = &Fdlist_.back(); 
+  handler.receiver = receiver;
+
+  Handlers_[fd] = handler;
+}
+
+void Waiter::DeregisterFd(int fd)
+{
+  // deregister fd should be caught in event loop
+  
+  pollfd *info = Handlers_[fd].info;
+  Fdlist_.erase(Fdlist_.begin() - (info - &Fdlist_.front()));
+  Handlers_.erase(fd);
+}
+
+
+Waiter::Waiter(Action prepare, Action requested, Executor executor)
+{
+  prepare_ = prepare;
+  requested_ = requested;
+  executor_ = executor;
+}
+
+Waiter::~Waiter()
+{
+}
+
+int Waiter::WaitToLaunching(int argc, char *argv[])
+{
+#ifndef NO_TIZEN
+  auto on_create = [](bundle *extra, int type, void *user_data)
+  {
+    _DBG("on_create..."); // XXX
+    Waiter* waiter = static_cast<Waiter*>(user_data);
+    waiter->OnPrepare();
+  };
+
+  auto on_launch = [](int argc, char **argv, const char *app_path,
+      const char *appid, const char *pkgid,
+      const char *pkg_type, void *user_data) -> int
+  {
+    _DBG("on_launch..."); // XXX
+    Waiter* waiter = static_cast<Waiter*>(user_data);
+
+    _DBG ("app path : %s", app_path);
+    _DBG ("app id : %s", appid);
+    _DBG ("pkg id : %s", pkgid);
+    _DBG ("pkg type : %s", pkg_type);
+
+    AppInfo info = {
+      AppPath : app_path,
+      AppId : appid,
+      PkgId : pkgid,
+      PkgType : pkg_type
+    };
+
+    waiter->OnLaunchRequested(info);
+    return 0;
+  };
+
+  auto on_terminate = [](int argc, char **argv, void *user_data) -> int
+  {
+    _DBG("on_terminate..."); // XXX
+    
+    string app_root(aul_get_app_root_path());
+    Waiter* waiter = static_cast<Waiter*>(user_data);
+    waiter->executor_(argv[0], app_root, argc, argv);
+    return 0;
+  };
+
+  auto on_start_loop = [](void *user_data)
+  {
+    _DBG("on_start_loop..."); // XXX
+    Waiter* waiter = static_cast<Waiter*>(user_data);
+    waiter->OnWaiting();
+  };
+
+  auto on_quit_loop = [](void *user_data)
+  {
+    _DBG("on_quit_loop..."); // XXX
+    Waiter* waiter = static_cast<Waiter*>(user_data);
+    waiter->Stop();
+  };
+
+  auto on_add_fd = [](void *user_data, int fd, loader_receiver_cb receiver)
+  {
+    _DBG("on_add_fd..."); // XXX
+    Waiter* waiter = static_cast<Waiter*>(user_data);
+    waiter->RegisterFd(fd, receiver);
+  };
+
+  auto on_remove_fd = [](void *user_data, int fd)
+  {
+    _DBG("on_remove_fd..."); // XXX
+    Waiter* waiter = static_cast<Waiter*>(user_data);
+    waiter->DeregisterFd(fd);
+  };
+
+  _DBG("launcher wait..."); // XXX
+  loader_lifecycle_callback_s callbacks = {
+    .create = on_create,
+    .launch = on_launch,
+    .terminate = on_terminate
+  };
+
+       loader_adapter_s adapter = {
+               .loop_begin = on_start_loop,
+               .loop_quit = on_quit_loop,
+               .add_fd = on_add_fd,
+               .remove_fd = on_remove_fd
+       };
+
+  return launchpad_loader_main(argc, argv, &callbacks, &adapter, this);
+#else
+  if (argc < 2) return -1;
+  std::string app_path(argv[1]);
+  std::string app_root;
+  auto pos = app_path.find_last_of('/');
+  if (pos != std::string::npos)
+    app_root = app_path.substr(0, pos);
+  else
+    app_root = ".";
+
+  this->OnPrepare();
+    AppInfo info = {
+      AppPath : argv[1],
+      AppId : "",
+      PkgId : "",
+      PkgType : ""
+    };
+  this->OnLaunchRequested(info);
+  this->executor_(app_path, app_root, argc, argv);
+#endif
+}
+
+}  // namespace runtime
+}  // namespace dotnet
diff --git a/NativeLauncher/src/waiter.h b/NativeLauncher/src/waiter.h
new file mode 100644 (file)
index 0000000..f233317
--- /dev/null
@@ -0,0 +1,46 @@
+#include <string>
+#include <functional>
+
+using std::string;
+
+namespace dotnet {
+namespace runtime {
+
+using Receiver = std::function<void(int)>;
+
+class Waiter
+{
+  public:
+    struct AppInfo
+    {
+      string AppPath;
+      string AppId;
+      string PkgId;
+      string PkgType;
+    };
+    using Action = std::function<void(void)>;
+    using Executor = std::function<void(const string&, const string&, int, char**)>;
+
+    Waiter(Action prepare, Action requested, Executor executor);
+    ~Waiter();
+
+    int WaitToLaunching(int argc, char *argv[]);
+    void Stop();
+
+    void RegisterFd(int fd, Receiver receiver);
+    void DeregisterFd(int fd);
+
+  protected:
+    void OnPrepare();
+    void OnLaunchRequested(const AppInfo&);
+    void OnWaiting();
+
+  private:
+
+    Action prepare_; 
+    Action requested_;
+    Executor executor_;
+};
+
+}  // namespace runtime
+}  // namespace dotnet
diff --git a/Tizen.Runtime/Tizen.CoreFX.Ref.Targets b/Tizen.Runtime/Tizen.CoreFX.Ref.Targets
new file mode 100644 (file)
index 0000000..f2484c1
--- /dev/null
@@ -0,0 +1,47 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+       
+       <PropertyGroup>
+               <CoreFXRefPath>/opt/usr/share/tizen.net/ref</CoreFXRefPath>
+               <TizenDeviceAPIPath>/usr/share/assembly</TizenDeviceAPIPath>
+       </PropertyGroup>
+
+       <PropertyGroup>
+               <NoCompilerStandardLib Condition=" '$(NoCompilerStandardLib)' == '' ">true</NoCompilerStandardLib>
+               <NoStdLib Condition=" '$(NoStdLib)' == '' ">true</NoStdLib>
+               <AdditionalLibPaths>$(CoreFXRefPath);$(TizenDeviceAPIPath)</AdditionalLibPaths>
+               <AddAdditionalExplicitAssemblyReferences>false</AddAdditionalExplicitAssemblyReferences>
+               <!-- Temporary suppress the warning... -->
+               <NoWarn>1701</NoWarn>
+       </PropertyGroup>
+
+       <ItemGroup>
+               <CoreFXRefDir Include="$(CoreFXRefPath)" Condition="Exists('$(CoreFXRefPath)')"/>
+               <CoreFXRefAssemblies Include="@(CoreFXRefDir->'%(FullPath)/*.dll')" Exclude="@(CoreFXRefDir->'%(FullPath)/mscorlib.dll')"/>
+
+               <TizenDeviceAPIDir Include="$(TizenDeviceAPIPath)" Condition="Exists('$(TizenDeviceAPIPath)')"/>
+               <TizenDeviceAPIAssemblies Include="@(TizenDeviceAPIDir->'%(FullPath)/*.dll')"/>
+       </ItemGroup>
+
+       <ItemGroup>
+               <ReferencePath Include="@(CoreFXRefAssemblies->'%(Filename).dll')"/>
+               <ReferencePath Include="@(TizenDeviceAPIAssemblies->'%(Filename).dll')"/>
+       </ItemGroup>
+
+       <Target Name="BeforeBuild">
+               <Message Text="[CoreFX Reference Environment!]"/>
+               <Message Text="CoreFX dir = $(CoreFXRefPath)"/>
+               <Message Text="CoreFX dir Check Ok" Condition="Exists('$(CoreFXRefPath)')"/>
+               <Message Text="Tizen Device API dir = $(TizenDeviceAPIPath)"/>
+               <Message Text="Tizen Device API Check Ok" Condition="Exists('$(TizenDeviceAPIPath)')"/>
+               <Message Text="CoreFXRefDir = @(CoreFXRefDir)"/>
+               <Message Text="TizenDeviceAPIDir = @(TizenDeviceAPIDir)"/>
+               <Message Text="CoreFXRefDir.Identity = %(CoreFXRefDir.Identity)"/>
+               <Message Text="TizenDeviceAPIDir.Identity = %(TizenDeviceAPIDir.Identity)"/>
+               <Message Text="CoreFXRefAssemblies = %(CoreFXRefAssemblies.Identity)"/>
+               <Message Text="TizenDeviceAPIAssemblies = %(TizenDeviceAPIAssemblies.Identity)"/>
+       </Target>
+
+       <PropertyGroup>
+               <CheckConfigDependsOn>CheckEnvironment</CheckConfigDependsOn>
+       </PropertyGroup>
+</Project>
diff --git a/Tizen.Runtime/Tizen.Runtime.csproj b/Tizen.Runtime/Tizen.Runtime.csproj
new file mode 100644 (file)
index 0000000..ffe4d9c
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project InitialTargets="CheckConfig" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+       
+       <PropertyGroup>
+               <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <OutputType>Library</OutputType>
+               <AssemblyName>Tizen.Runtime</AssemblyName>
+       </PropertyGroup>
+
+       <PropertyGroup Condition=" '$(Configuration)' == 'Debug'">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+               <OutputPath>bin/</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+       </PropertyGroup>
+
+       <PropertyGroup Condition=" '$(Configuration)' == 'Release'">
+               <DebugType>pdbonly</DebugType>
+               <Optimize>true</Optimize>
+               <OutputPath>bin/</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+       </PropertyGroup>
+
+       <PropertyGroup>
+               <SignAssembly>true</SignAssembly>
+               <AssemblyOriginatorKeyFile>Tizen.Runtime.snk</AssemblyOriginatorKeyFile>
+       </PropertyGroup>
+
+       <ItemGroup>
+               <Compile Include="Tizen.Runtime/AssemblyLoader.cs" />
+               <Compile Include="Tizen.Runtime/Log.cs" />
+               <Compile Include="Tizen.Runtime/AssemblyManager.cs" />
+       </ItemGroup>
+
+       <Target Name="CheckConfig">
+               <Message Text="MSBuildProjectDirectory = $(MSBuildProjectDirectory)"/>
+       </Target>
+
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+       <Import Project="$(MSBuildProjectDirectory)/Tizen.CoreFX.Ref.Targets" />
+</Project>
diff --git a/Tizen.Runtime/Tizen.Runtime.snk b/Tizen.Runtime/Tizen.Runtime.snk
new file mode 100644 (file)
index 0000000..758e318
Binary files /dev/null and b/Tizen.Runtime/Tizen.Runtime.snk differ
diff --git a/Tizen.Runtime/Tizen.Runtime/AssemblyLoader.cs b/Tizen.Runtime/Tizen.Runtime/AssemblyLoader.cs
new file mode 100644 (file)
index 0000000..e959146
--- /dev/null
@@ -0,0 +1,45 @@
+using System;
+using System.IO;
+using System.Reflection;
+using System.Runtime.Loader;
+using System.Collections.Generic;
+
+namespace Tizen.Runtime
+{
+    public class AssemblyLoader : AssemblyLoadContext
+    {
+        private SortedSet<string> _dllDirectories = new SortedSet<string>();
+        public IEnumerable<string> DllDirectories
+        {
+            get { return _dllDirectories; }
+        }
+
+        public void AddSearchableDirectory(string directory)
+        {
+            if (Directory.Exists(directory))
+            {
+                _dllDirectories.Add(directory);
+            }
+        }
+
+        public void RemoveSearchableDirectory(string directory)
+        {
+            _dllDirectories.Remove(directory);
+        }
+
+        protected override Assembly Load(AssemblyName assemblyName)
+        {
+            ALog.Debug($"Load!! : {assemblyName.Name}");
+            foreach (string dir in DllDirectories)
+            {
+                FileInfo f = new FileInfo(Path.Combine(dir, $"{assemblyName.Name}.dll"));
+                ALog.Debug(f.FullName);
+                if (File.Exists(f.FullName))
+                {
+                    return LoadFromAssemblyPath(f.FullName);
+                }
+            }
+            return Assembly.Load(assemblyName);
+        }
+    }
+}
diff --git a/Tizen.Runtime/Tizen.Runtime/AssemblyManager.cs b/Tizen.Runtime/Tizen.Runtime/AssemblyManager.cs
new file mode 100644 (file)
index 0000000..f7a7810
--- /dev/null
@@ -0,0 +1,87 @@
+using System;
+using System.IO;
+using System.Reflection;
+using System.Runtime.Loader;
+
+namespace Tizen.Runtime
+{
+    public static class AssemblyManager
+    {
+        private static void PrintException(Exception exception)
+        {
+            while (exception != null)
+            {
+                ALog.Debug(exception.Message);
+                ALog.Debug(exception.StackTrace);
+                exception = exception.InnerException;
+            }
+        }
+
+        public static AssemblyLoader CurrentAssemblyLoaderContext
+        {
+            get;
+            private set;
+        }
+
+        public static bool Initialize(string searchableDirectories, string preloadDllPaths)
+        {
+            try
+            {
+                CurrentAssemblyLoaderContext = new AssemblyLoader();
+
+                if (searchableDirectories != null)
+                {
+                    string[] dirs = searchableDirectories.Split(':');
+                    foreach (string dir in dirs)
+                    {
+                        CurrentAssemblyLoaderContext.AddSearchableDirectory(dir);
+                    }
+                }
+
+                if (preloadDllPaths != null)
+                {
+                    string[] dllPaths = preloadDllPaths.Split(':');
+                    foreach (string dllPath in dllPaths)
+                    {
+                        FileInfo f = new FileInfo(dllPath);
+                        if (File.Exists(f.FullName))
+                        {
+                            CurrentAssemblyLoaderContext.LoadFromAssemblyPath(f.FullName);
+                        }
+                    }
+                }
+            }
+            catch (Exception e)
+            {
+                ALog.Debug("Exception on Initialized");
+                PrintException(e);
+                return false;
+            }
+            return true;
+        }
+
+        public static void Execute(string dllPath)
+        {
+            try
+            {
+                FileInfo f = new FileInfo(dllPath);
+                if (File.Exists(f.FullName))
+                {
+                    Assembly asm = CurrentAssemblyLoaderContext.LoadFromAssemblyPath(f.FullName);
+                    if (asm == null) throw new FileNotFoundException($"{f.FullName} is not found");
+                    if (asm.EntryPoint == null) throw new ArgumentException($"{f.FullName} did not have EntryPoint");
+                    asm.EntryPoint.Invoke(null, new string[]{null});
+                }
+            }
+            catch (Exception e)
+            {
+                ALog.Debug("Exception on Execute");
+                PrintException(e);
+            }
+        }
+
+        public static void Finish()
+        {
+        }
+    }
+}
diff --git a/Tizen.Runtime/Tizen.Runtime/Log.cs b/Tizen.Runtime/Tizen.Runtime/Log.cs
new file mode 100644 (file)
index 0000000..064a5f3
--- /dev/null
@@ -0,0 +1,55 @@
+using System;
+#if !CLOG
+using Tizen;
+#endif
+
+namespace Tizen.Runtime
+{
+#if CLOG
+    internal static class Log
+    {
+        static void Print(string tag, string message)
+        {
+            string[] lines = message.Split('\r');
+            foreach (string line in lines)
+            {
+                Console.WriteLine($"{tag} : {message}");
+            }
+        }
+
+        public static void Debug(string tag, string message)
+        {
+            Print($"D/{tag}", message);
+        }
+
+        public static void Info(string tag, string message)
+        {
+            Print($"I/{tag}", message);
+        }
+
+        public static void Error(string tag, string message)
+        {
+            Print($"E/{tag}", message);
+        }
+    }
+#endif
+    internal static class ALog
+    {
+        static string TAG = "Tizen.Runtime";
+
+        public static void Debug(string message)
+        {
+            Log.Debug(TAG, message);
+        }
+
+        public static void Info(string message)
+        {
+            Log.Info(TAG, message);
+        }
+
+        public static void Error(string message)
+        {
+            Log.Error(TAG, message);
+        }
+    }
+}
diff --git a/Tizen.Runtime/Tizen.Runtime/test.cs b/Tizen.Runtime/Tizen.Runtime/test.cs
new file mode 100644 (file)
index 0000000..1c65dbe
--- /dev/null
@@ -0,0 +1,21 @@
+using Tizen.Runtime;
+
+public class Program
+{
+    public static void Main(string[] args)
+    {
+        if (args.Length < 2)
+        {
+            ALog.Debug("Cancel..");
+            return;
+        }
+        string preload = Environment.GetEnvironmentVariable("PRELOAD_DLLS");
+        string searchable = String.Join(":", args, 1, args.Length - 1);
+
+        if (AssemblyManager.Initialize(searchable, preload))
+        {
+            ALog.Debug("After Initialized...");
+            AssemblyManager.Execute(args[0]);
+        }
+    }
+}
diff --git a/packaging/dotnet-launcher.ini b/packaging/dotnet-launcher.ini
deleted file mode 100644 (file)
index 9d4809c..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-[dotnet]
-libcoreclr = libcoreclr.so
-coreclr_dir = /opt/usr/share/dotnet/shared/Microsoft.NETCore.App/1.0.0
-tpa_dirs = /opt/usr/share/dotnet/shared/Microsoft.NETCore.App/1.0.0:/usr/share/assembly
-native_so_search_dirs = /opt/usr/share/dotnet/shared/Microsoft.NETCore.App/1.0.0:/usr/share/assembly
index 2bbc40aea656817a93ceab7b1d6affebebcb47ea..353ab993ddad0950a95ea175fc72f7fd32c4a472 100644 (file)
@@ -13,6 +13,10 @@ BuildRequires: pkgconfig(dlog)
 BuildRequires: pkgconfig(ecore)
 BuildRequires: pkgconfig(launchpad)
 BuildRequires: aul-devel
+BuildRequires: corefx-managed-32b-ref
+BuildRequires: mono-compiler
+BuildRequires: mono-devel 
+BuildRequires: csapi-tizen 
 Requires: aul
 
 Requires(post): /sbin/ldconfig
@@ -43,16 +47,21 @@ cmake \
        -DLOADERDIR=%{_loaderdir} \
        -DCONFIGDIR=%{_configdir} \
        -DCMAKE_BUILD_TYPE=%{_buildmode} \
-       -DVERSION=%{version}
+       -DVERSION=%{version} \
+       NativeLauncher
 
 make %{?jobs:-j%jobs}
 
+xbuild /p:Configuration=%{_buildmode} Tizen.Runtime/Tizen.Runtime.csproj
+
 %install
 rm -rf %{buildroot}
 %make_install
+install -p -m 644 Tizen.Runtime/bin/Tizen.Runtime.dll %{buildroot}%{_bindir}
 
 %files
 %manifest dotnet-launcher.manifest
 %config /etc/dotnet-launcher.ini
 %{_loaderdir}/dotnet.loader
 %caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/dotnet-launcher
+%caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/Tizen.Runtime.dll
diff --git a/packaging/dotnet.loader b/packaging/dotnet.loader
deleted file mode 100644 (file)
index 67094b9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-[LOADER]
-NAME    dotnet-launcher
-EXE     /usr/bin/dotnet-launcher
-APP_TYPE        dotnet
-DETECTION_METHOD        TIMEOUT|DEMAND
-TIMEOUT         5000
diff --git a/src/environment.h b/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__
diff --git a/src/launcher.cc b/src/launcher.cc
deleted file mode 100644 (file)
index fcd1555..0000000
+++ /dev/null
@@ -1,414 +0,0 @@
-#include <dlfcn.h>
-
-#ifdef LAUNCHING_TIME_MEASURE
-#include <ctime>
-#endif
-
-#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 "environment.h"
-#include "waiter.h"
-#include "log.h"
-
-#include "tini.hpp"
-
-#include "launcher.h"
-
-namespace dotnet {
-namespace runtime {
-
-#ifdef LAUNCHER_PATH
-#define __STR(x) #x
-#define __XSTR(x) __STR(x)
-#define LAUNCHER_CONFIG __XSTR(LAUNCHER_PATH)
-#else
-#define LAUNCHER_CONFIG "/etc/dotnet-launcher.ini"
-#endif
-static const std::string LauncherConfig(LAUNCHER_CONFIG);
-#ifdef LAUNCHER_PATH
-#undef __STR
-#undef __XSTR
-#undef LAUNCHER_CONFIG
-#undef LAUNCHER_PATH
-#endif
-
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR '/'
-#endif
-
-static 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;
-}
-static void AppendPath(std::string& path1, const std::string& path2)
-{
-  if (path1.back() == PATH_SEPARATOR)
-  {
-    path1.append(path2);
-  }
-  else
-  {
-    path1 += PATH_SEPARATOR;
-    path1.append(path2);
-  }
-}
-
-static 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;
-}
-
-static 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);
-  }
-  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)
-  {
-    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);
-
-  if (dir == nullptr)
-  {
-    _ERR("can not open directory : %s", directory);
-    return std::string();
-  }
-
-  std::set<std::string> addedAssemblies;
-
-  struct dirent *entry;
-
-  int tpaCount = sizeof(tpaExtensions) / sizeof(tpaExtensions[0]);
-  for (int i=0; i<tpaCount; i++)
-  {
-    const std::string& ext = tpaExtensions[i];
-    bool isNativeExt = tpaExtensions_ni[i];
-
-    while ((entry = readdir(dir)) != nullptr)
-    {
-      switch (entry->d_type)
-      {
-        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:
-          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 + ':';
-      }
-    }
-    rewinddir(dir);
-  }
-
-  closedir(dir);
-  return tpaList;
-}
-
-Launcher::Launcher()
-{
-}
-
-Launcher::~Launcher()
-{
-}
-
-void Launcher::Initialize()
-{
-#ifdef LAUNCHING_TIME_MEASURE
-  std::clock_t start = std::clock();
-#endif
-
-  std::ifstream iniStream(LauncherConfig);
-  std::stringstream iniString;
-  iniString << iniStream.rdbuf();
-  tini::ini launcherIni(iniString);
-
-  _DBG("config file [%s]", LauncherConfig.c_str());
-  _DBG("%s", launcherIni.to_string().c_str());
-
-  auto &dotnet = launcherIni["dotnet"];
-  if (dotnet.find("libcoreclr") == dotnet.end())
-    dotnet["libcoreclr"] = "libcoreclr.so";
-  if (dotnet.find("coreclr_dir") == dotnet.end())
-    dotnet["coreclr_dir"] = "/usr/share/dotnet";
-  if (dotnet.find("tpa_dir") == dotnet.end())
-    dotnet["tpa_dir"] = dotnet["coreclr_dir"] + ":" + "/usr/share/assemblies";
-  if (dotnet.find("native_so_search_dirs") == dotnet.end())
-    dotnet["native_so_search_dirs"] = dotnet["tpa_dir"];
-
-  _DBG("libcoreclr : %s", dotnet["libcoreclr"].c_str());
-  _DBG("coreclr_dir : %s", dotnet["coreclr_dir"].c_str());
-  _DBG("tpa_dir : %s", dotnet["tpa_dir"].c_str());
-  _DBG("native_so_search_dirs : %s", dotnet["native_so_search_dirs"].c_str());
-
-  std::string libcoreclr = dotnet["coreclr_dir"] + "/" + dotnet["libcoreclr"];
-  std::string tpaDirs = dotnet["tpa_dirs"];
-  std::string nativeSoSearchDirs = dotnet["native_so_search_dirs"];
-
-  _DBG("libcoreclr.so : [%s]", libcoreclr.c_str());
-
-#ifdef LAUNCHING_TIME_MEASURE
-  std::clock_t config_read_time = std::clock();
-  _DBG("Reading Config file... : %Lf ms ", (config_read_time - start) / (double)(CLOCKS_PER_SEC / 1000));
-#endif
-
-  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;
-  }
-
-  initializeCoreCLR = (coreclr_initialize_ptr)dlsym(coreclrLib, "coreclr_initialize");
-  executeAssembly = (coreclr_execute_assembly_ptr)dlsym(coreclrLib, "coreclr_execute_assembly");
-  shutdownCoreCLR = (coreclr_shutdown_ptr)dlsym(coreclrLib, "coreclr_shutdown");
-
-  if (initializeCoreCLR == nullptr)
-  {
-    _ERR("coreclr_initialize not found in the libcoreclr.so");
-  }
-  else if (executeAssembly == nullptr)
-  {
-    _ERR("coreclr_execute_assembly_ptr not found in the libcoreclr.so");
-  }
-  else if (shutdownCoreCLR == nullptr)
-  {
-    _ERR("coreclr_shutdown_ptr not found in the libcoreclr.so");
-  }
-  else
-  {
-    std::istringstream f(tpaDirs);
-    std::string s;
-    while (std::getline(f, s, ':'))
-    {
-      TrustedPlatformAssemblies += AssembliesInDirectory(s.c_str());
-    }
-    NativeDllSearchDirectories = nativeSoSearchDirs; 
-    AppDomainCompatSwitch = "UseLatestBehaviorWhenTFMNotSpecified";
-  }
-
-#ifdef LAUNCHING_TIME_MEASURE
-  std::clock_t dlopen_time = std::clock();
-  _DBG("dlopen and dlsym time... : %Lf ms ", (dlopen_time - config_read_time) / (double)(CLOCKS_PER_SEC / 1000));
-  _DBG("initialize time... : %Lf ms ", (dlopen_time - start) / (double)(CLOCKS_PER_SEC / 1000));
-#endif
-
-}
-
-void Launcher::Launch(const string& exe_path, const string& app_root, int argc, char *argv[])
-{
-  std::string bin_path = Basename(AbsolutePath(exe_path));
-  std::string lib_path = ConcatPath(AbsolutePath(app_root), "lib");
-  std::string app_path = bin_path + ":" + lib_path;
-  std::string app_ni_path = app_path;
-  std::string nativeDllSearchDirectories = NativeDllSearchDirectories + app_path;
-
-  const char *propertyKeys[] =
-  {
-    "TRUSTED_PLATFORM_ASSEMBLIES",
-    "APP_PATHS",
-    "APP_NI_PATHS",
-    "NATIVE_DLL_SEARCH_DIRECTORIES",
-    "AppDomainCompatSwitch"
-  };
-
-  const char *propertyValues[] =
-  {
-    TrustedPlatformAssemblies.c_str(),
-    app_path.c_str(),
-    app_ni_path.c_str(),
-    nativeDllSearchDirectories.c_str(),
-    AppDomainCompatSwitch.c_str()
-  };
-
-  //_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]);
-
-  void* hostHandle;
-  unsigned int domainId;
-
-  _DBG("before initialize coreclr");
-
-#ifdef LAUNCHING_TIME_MEASURE
-  std::clock_t start = std::clock();
-#endif
-  int st = initializeCoreCLR(exe_path.c_str(),
-      "tizen_dotnet_launcher",
-      sizeof(propertyKeys) / sizeof(propertyKeys[0]),
-      propertyKeys,
-      propertyValues,
-      &hostHandle,
-      &domainId);
-
-  _DBG("after initialize coreclr");
-#ifdef LAUNCHING_TIME_MEASURE
-  std::clock_t initialize_coreclr_time = std::clock();
-  _DBG("call coreclr_initialize ... : %Lf ms ", (initialize_coreclr_time - start) / (double)(CLOCKS_PER_SEC / 1000));
-#endif
-  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");
-  }
-  else
-  {
-    unsigned int exitCode;
-    const char** argvc = const_cast<const char**>(argv);
-    st = executeAssembly(hostHandle, domainId, argc, argvc, exe_path.c_str(), &exitCode);
-    _DBG("after execute coreclr");
-    if (st < 0)
-    {
-      // execute coreclr fail
-      _ERR("execute core clr fail! (0x%08x / %d)", st, exitCode);
-    }
-    st = shutdownCoreCLR(hostHandle, domainId);
-    if (st < 0)
-    {
-      // shutdown fail
-      _ERR("shutdown core clr fail! (0x%08x)", st);
-    }
-#ifdef LAUNCHING_TIME_MEASURE
-    std::clock_t execute_assembly_time = std::clock();
-    _DBG("call execute_assembly_time ... : %Lf ms ", (execute_assembly_time - initialize_coreclr_time) / (double)(CLOCKS_PER_SEC / 1000));
-#endif
-  }
-  if (dlclose(coreclrLib) != 0)
-  {
-    _ERR("libcoreclr.so close failed");
-  }
-#ifdef LAUNCHING_TIME_MEASURE
-    std::clock_t after_launching_time = std::clock();
-    _DBG("launching end time ... : %Lf ms ", (after_launching_time - start) / (double)(CLOCKS_PER_SEC / 1000));
-#endif
-}
-
-}  // namespace runtime
-}  // namespace dotnet
-
-using dotnet::runtime::Launcher;
-using dotnet::runtime::Waiter;
-
-int main(int argc, char *argv[])
-{
-  _DBG("launcher started");
-
-  for (int i=0; i<argc; i++)
-  {
-    _DBG("argv[%d](%d) : [%s]", i, strlen(argv[i]), argv[i]);
-  }
-
-  std::unique_ptr<Launcher> launcher(new Launcher());
-  auto on_prepare = [&launcher]()
-  {
-    launcher->Initialize();
-  };
-  auto on_requested = [&launcher]()
-  {
-  };
-  auto on_executed = [&launcher](const std::string& path, const std::string& app_root, int argc, char *argv[])
-  {
-    _DBG("EXECUTE %s", path.c_str());
-    launcher->Launch(path, app_root, argc, argv);
-  };
-  std::unique_ptr<Waiter> waiter(new Waiter(on_prepare, on_requested, on_executed));
-  waiter->WaitToLaunching(argc, argv);
-}
diff --git a/src/launcher.h b/src/launcher.h
deleted file mode 100644 (file)
index acba908..0000000
+++ /dev/null
@@ -1,52 +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);
-
-using std::string;
-using std::vector;
-
-class Launcher
-{
-  public:
-    Launcher();
-    ~Launcher();
-    void Initialize();
-    void Launch(const string& exe_path, const string& app_root, int argc, char *argv[]);
-
-  private:
-    coreclr_initialize_ptr initializeCoreCLR;
-    coreclr_execute_assembly_ptr executeAssembly;
-    coreclr_shutdown_ptr shutdownCoreCLR;
-
-    string TrustedPlatformAssemblies;
-    string NativeDllSearchDirectories;
-    string AppDomainCompatSwitch;
-
-    void *coreclrLib;
-};
-
-}  // namespace runtime
-}  // namespace dotnet
diff --git a/src/log.h b/src/log.h
deleted file mode 100644 (file)
index 59f2dc9..0000000
--- a/src/log.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef __LOG_H__
-#define __LOG_H__
-
-#ifndef NO_TIZEN
-#include <dlog.h>
-#else
-#include <stdio.h>
-#define LOGE(fmt, args...) printf(fmt, ##args)
-#define LOGD(fmt, args...) printf(fmt, ##args)
-#define LOGI(fmt, args...) printf(fmt, ##args)
-#endif
-
-#ifdef  LOG_TAG
-#undef  LOG_TAG
-#endif
-#define LOG_TAG "NETCORE_LAUNCHER"
-
-#ifndef _ERR
-#define _ERR(fmt, args...) LOGE(fmt "\n", ##args)
-#endif
-
-#ifndef _DBG
-#define _DBG(fmt, args...) LOGD(fmt "\n", ##args)
-#endif
-
-#ifndef _INFO
-#define _INFO(fmt, args...) LOGI(fmt "\n", ##args)
-#endif
-
-#endif /* __LOG_H__ */
diff --git a/src/tini.hpp b/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/src/waiter.cc b/src/waiter.cc
deleted file mode 100644 (file)
index 6f83482..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-
-#include <poll.h>
-
-#ifndef NO_TIZEN
-#include <launchpad.h>
-#include <aul.h>
-#endif
-
-#include <memory>
-#include <vector>
-#include <map>
-#include <poll.h>
-
-#include <iostream>
-
-#include "waiter.h"
-#include "log.h"
-
-namespace dotnet {
-namespace runtime {
-
-struct FdHandler
-{
-  pollfd *info;
-  Receiver receiver;
-};
-
-static volatile bool Waiting_;
-static std::vector<pollfd> Fdlist_;
-static std::map<int, FdHandler> Handlers_;
-static Waiter::AppInfo AppInfo_;
-
-void Waiter::OnPrepare()
-{
-  // preload the libraries.
-  if (prepare_ != nullptr)
-    prepare_();
-}
-
-void Waiter::OnLaunchRequested(const AppInfo& info)
-{
-  // do some job on user id is still system
-}
-
-void Waiter::OnWaiting()
-{
-  // Start the loop
-  Waiting_ = true;
-
-  _DBG("start polling...");
-  while (Waiting_)
-  {
-    if (poll(Fdlist_.data(), Fdlist_.size(), -1) < 0)
-      continue;
-
-    for (auto &p : Fdlist_)
-    {
-      if ( (p.revents | POLLIN) != 0 )
-        Handlers_[p.fd].receiver(p.fd);
-    }
-  }
-  _DBG("end polling...");
-}
-
-void Waiter::Stop()
-{
-  // Stop the loop
-
-  Waiting_ = false;
-}
-
-
-void Waiter::RegisterFd(int fd, Receiver receiver)
-{
-  // register fd should be caught in event loop
-
-  _DBG("Register fd %d", fd);
-
-  pollfd info;
-  info.fd = fd;
-  info.events = POLLIN;
-  info.revents = 0;
-
-  FdHandler handler;
-  Fdlist_.push_back(info);
-  handler.info = &Fdlist_.back(); 
-  handler.receiver = receiver;
-
-  Handlers_[fd] = handler;
-}
-
-void Waiter::DeregisterFd(int fd)
-{
-  // deregister fd should be caught in event loop
-  
-  pollfd *info = Handlers_[fd].info;
-  Fdlist_.erase(Fdlist_.begin() - (info - &Fdlist_.front()));
-  Handlers_.erase(fd);
-}
-
-
-Waiter::Waiter(Action prepare, Action requested, Executor executor)
-{
-  prepare_ = prepare;
-  requested_ = requested;
-  executor_ = executor;
-}
-
-Waiter::~Waiter()
-{
-}
-
-int Waiter::WaitToLaunching(int argc, char *argv[])
-{
-#ifndef NO_TIZEN
-  auto on_create = [](bundle *extra, int type, void *user_data)
-  {
-    _DBG("on_create..."); // XXX
-    Waiter* waiter = static_cast<Waiter*>(user_data);
-    waiter->OnPrepare();
-  };
-
-  auto on_launch = [](int argc, char **argv, const char *app_path,
-      const char *appid, const char *pkgid,
-      const char *pkg_type, void *user_data) -> int
-  {
-    _DBG("on_launch..."); // XXX
-    Waiter* waiter = static_cast<Waiter*>(user_data);
-
-    _DBG ("app path : %s", app_path);
-    _DBG ("app id : %s", appid);
-    _DBG ("pkg id : %s", pkgid);
-    _DBG ("pkg type : %s", pkg_type);
-
-    AppInfo info = {
-      AppPath : app_path,
-      AppId : appid,
-      PkgId : pkgid,
-      PkgType : pkg_type
-    };
-
-    waiter->OnLaunchRequested(info);
-    return 0;
-  };
-
-  auto on_terminate = [](int argc, char **argv, void *user_data) -> int
-  {
-    _DBG("on_terminate..."); // XXX
-    
-    string app_root(aul_get_app_root_path());
-    Waiter* waiter = static_cast<Waiter*>(user_data);
-    waiter->executor_(argv[0], app_root, argc, argv);
-    return 0;
-  };
-
-  auto on_start_loop = [](void *user_data)
-  {
-    _DBG("on_start_loop..."); // XXX
-    Waiter* waiter = static_cast<Waiter*>(user_data);
-    waiter->OnWaiting();
-  };
-
-  auto on_quit_loop = [](void *user_data)
-  {
-    _DBG("on_quit_loop..."); // XXX
-    Waiter* waiter = static_cast<Waiter*>(user_data);
-    waiter->Stop();
-  };
-
-  auto on_add_fd = [](void *user_data, int fd, loader_receiver_cb receiver)
-  {
-    _DBG("on_add_fd..."); // XXX
-    Waiter* waiter = static_cast<Waiter*>(user_data);
-    waiter->RegisterFd(fd, receiver);
-  };
-
-  auto on_remove_fd = [](void *user_data, int fd)
-  {
-    _DBG("on_remove_fd..."); // XXX
-    Waiter* waiter = static_cast<Waiter*>(user_data);
-    waiter->DeregisterFd(fd);
-  };
-
-  _DBG("launcher wait..."); // XXX
-  loader_lifecycle_callback_s callbacks = {
-    .create = on_create,
-    .launch = on_launch,
-    .terminate = on_terminate
-  };
-
-       loader_adapter_s adapter = {
-               .loop_begin = on_start_loop,
-               .loop_quit = on_quit_loop,
-               .add_fd = on_add_fd,
-               .remove_fd = on_remove_fd
-       };
-
-  return launchpad_loader_main(argc, argv, &callbacks, &adapter, this);
-#else
-  if (argc < 2) return -1;
-  std::string app_path(argv[1]);
-  std::string app_root;
-  auto pos = app_path.find_last_of('/');
-  if (pos != std::string::npos)
-    app_root = app_path.substr(0, pos);
-  else
-    app_root = ".";
-
-  this->OnPrepare();
-    AppInfo info = {
-      AppPath : argv[1],
-      AppId : "",
-      PkgId : "",
-      PkgType : ""
-    };
-  this->OnLaunchRequested(info);
-  this->executor_(app_path, app_root, argc, argv);
-#endif
-}
-
-}  // namespace runtime
-}  // namespace dotnet
diff --git a/src/waiter.h b/src/waiter.h
deleted file mode 100644 (file)
index f233317..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#include <string>
-#include <functional>
-
-using std::string;
-
-namespace dotnet {
-namespace runtime {
-
-using Receiver = std::function<void(int)>;
-
-class Waiter
-{
-  public:
-    struct AppInfo
-    {
-      string AppPath;
-      string AppId;
-      string PkgId;
-      string PkgType;
-    };
-    using Action = std::function<void(void)>;
-    using Executor = std::function<void(const string&, const string&, int, char**)>;
-
-    Waiter(Action prepare, Action requested, Executor executor);
-    ~Waiter();
-
-    int WaitToLaunching(int argc, char *argv[]);
-    void Stop();
-
-    void RegisterFd(int fd, Receiver receiver);
-    void DeregisterFd(int fd);
-
-  protected:
-    void OnPrepare();
-    void OnLaunchRequested(const AppInfo&);
-    void OnWaiting();
-
-  private:
-
-    Action prepare_; 
-    Action requested_;
-    Executor executor_;
-};
-
-}  // namespace runtime
-}  // namespace dotnet