Add PluginsLauncher and DynamicLibHandle 41/57241/10
authorKamil Chlodnicki <k.chlodnicki@samsung.com>
Mon, 18 Jan 2016 10:19:07 +0000 (11:19 +0100)
committerTomasz Iwanek <t.iwanek@samsung.com>
Thu, 28 Jan 2016 09:56:00 +0000 (01:56 -0800)
This change adds the class PluginsLauncher which is to be used by
StepRunParserPlugin. The DynamicLibHandle class is used by PluginsLauncher
to manage plugins which are in the form of dynamic libraries.
This commit can be submitted independently, however to launch plugins
(via PluginLauncher class) StepRunParserPlugin needs to be submitted too.

Change-Id: I55daa5f8d8867e4716530db5d6c9319526bf02fe

src/common/CMakeLists.txt
src/common/plugins_launcher.cc [new file with mode: 0644]
src/common/plugins_launcher.h [new file with mode: 0644]
src/common/utils/dynamic_lib_handle.cc [new file with mode: 0644]
src/common/utils/dynamic_lib_handle.h [new file with mode: 0644]

index 45422d2..02093eb 100644 (file)
@@ -6,6 +6,7 @@ SET(SRCS
   pkgmgr_interface.cc
   pkgmgr_registration.cc
   pkgmgr_signal.cc
+  plugins_launcher.cc
   recovery_file.cc
   request.cc
   security_registration.cc
@@ -47,6 +48,7 @@ SET(SRCS
   step/step_update_app.cc
   step/step_update_security.cc
   step/step_update_tep.cc
+  utils/dynamic_lib_handle.cc
   utils/file_util.cc
   utils/subprocess.cc
 )
diff --git a/src/common/plugins_launcher.cc b/src/common/plugins_launcher.cc
new file mode 100644 (file)
index 0000000..b9ed627
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "common/plugins_launcher.h"
+
+#include <dlfcn.h>
+
+#include <map>
+#include <utility>
+
+namespace common_installer {
+
+bool PluginsLauncher::LaunchPlugin(const boost::filesystem::path& plugin_path,
+                                   xmlDocPtr docPtr, ActionType action,
+                                   const std::string& pkgId, int* result) {
+  LOG(DEBUG) << "Installing plugin: " << plugin_path;
+
+  std::unique_ptr<DynamicLibHandle> dl_handle =
+      DynamicLibHandle::Create(plugin_path, RTLD_LAZY | RTLD_LOCAL);
+  if (!dl_handle) {
+    LOG(ERROR) << "Failed to create library handle";
+    return false;
+  }
+
+  if (!RunPluginFunction(dl_handle.get(), ProcessType::PreInstall, action,
+                         pkgId.c_str(), result)) {
+    LOG(ERROR) << "Preinstall failed";
+    return false;
+  }
+
+  if (!RunPluginFunction(dl_handle.get(), ProcessType::Install, action,
+                         docPtr, pkgId.c_str(), result)) {
+    LOG(ERROR) << "Install failed";
+    return false;
+  }
+  if (!RunPluginFunction(dl_handle.get(), ProcessType::PostInstall, action,
+                         pkgId.c_str(), result)) {
+    LOG(ERROR) << "Postinstall failed";
+    return false;
+  }
+  return true;
+}
+
+bool PluginsLauncher::GetName(ProcessType process, ActionType action,
+                              std::string* result) {
+  static std::map<std::pair<ActionType, ProcessType>, std::string> names {
+    {{ActionType::Install,   ProcessType::PreInstall},  "PKGMGR_PARSER_PLUGIN_PRE_INSTALL"},  // NOLINT
+    {{ActionType::Upgrade,   ProcessType::PreInstall},  "PKGMGR_PARSER_PLUGIN_PRE_UPGRADE"},  // NOLINT
+    {{ActionType::Uninstall, ProcessType::PreInstall},  "PKGMGR_PARSER_PLUGIN_PRE_UNINSTALL"},  // NOLINT
+    {{ActionType::Install,   ProcessType::Install},     "PKGMGR_PARSER_PLUGIN_INSTALL"},  // NOLINT
+    {{ActionType::Upgrade,   ProcessType::Install},     "PKGMGR_PARSER_PLUGIN_UPGRADE"},  // NOLINT
+    {{ActionType::Uninstall, ProcessType::Install},     "PKGMGR_PARSER_PLUGIN_UNINSTALL"},  // NOLINT
+    {{ActionType::Install,   ProcessType::PostInstall}, "PKGMGR_PARSER_PLUGIN_POST_INSTALL"},  // NOLINT
+    {{ActionType::Upgrade,   ProcessType::PostInstall}, "PKGMGR_PARSER_PLUGIN_POST_UPGRADE"},  // NOLINT
+    {{ActionType::Uninstall, ProcessType::PostInstall}, "PKGMGR_PARSER_PLUGIN_POST_UNINSTALL"}  // NOLINT
+  };
+
+  auto pos = names.find(std::make_pair(action, process));
+  if (pos == names.end()) {
+    LOG(ERROR) << "Function name not defined";
+    return false;
+  }
+  *result = pos->second;
+  return true;
+}
+
+bool PluginsLauncher::RunPluginFunction(DynamicLibHandle* dl_handle,
+                                        ProcessType process, ActionType action,
+                                        const char* pkgId, int* result) {
+  return RunPluginFunctionImpl(dl_handle, process, action, result, pkgId);
+}
+
+bool PluginsLauncher::RunPluginFunction(DynamicLibHandle* dl_handle,
+                                        ProcessType process, ActionType action,
+                                        xmlDocPtr docPtr, const char* pkgId,
+                                        int* result) {
+  return RunPluginFunctionImpl(dl_handle, process, action, result, docPtr,
+                               pkgId);
+}
+
+}  // namespace common_installer
diff --git a/src/common/plugins_launcher.h b/src/common/plugins_launcher.h
new file mode 100644 (file)
index 0000000..9849ae5
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_PLUGINS_LAUNCHER_H_
+#define COMMON_PLUGINS_LAUNCHER_H_
+
+#include <boost/filesystem/path.hpp>
+
+#include <libxml/tree.h>
+#include <manifest_parser/utils/logging.h>
+
+#include <string>
+#include <memory>
+
+#include "utils/dynamic_lib_handle.h"
+
+namespace common_installer {
+
+
+class PluginsLauncher {
+ public:
+  enum class ActionType { Install, Upgrade, Uninstall };
+  enum class ProcessType { PreInstall, Install, PostInstall };
+
+  bool LaunchPlugin(const boost::filesystem::path& plugin_path,
+                    xmlDocPtr docPtr, ActionType action,
+                    const std::string& pkgId, int* result);
+
+ private:
+  std::string GetPath(const std::string& plugin);
+  bool GetName(ProcessType process, ActionType action, std::string* result);
+
+  bool RunPluginFunction(DynamicLibHandle* dl_handle, ProcessType process,
+                         ActionType action, const char *pkgId, int *result);
+
+  bool RunPluginFunction(DynamicLibHandle* dl_handle, ProcessType process,
+                         ActionType action, xmlDocPtr docPtr, const char* pkgId,
+                         int *result);
+
+  template <typename... Args>
+  bool RunPluginFunctionImpl(DynamicLibHandle* dl_handle, ProcessType process,
+                             ActionType action, int *result, Args&&... args) {
+    std::string name;
+    if (!GetName(process, action, &name)) {
+      LOG(ERROR) << "Error during getting function name";
+      return false;
+    }
+    return dl_handle->run(name, result, std::forward<Args>(args)...);
+  }
+
+  SCOPE_LOG_TAG(PluginsLauncher)
+};
+
+}  // namespace common_installer
+
+#endif  // COMMON_PLUGINS_LAUNCHER_H_
diff --git a/src/common/utils/dynamic_lib_handle.cc b/src/common/utils/dynamic_lib_handle.cc
new file mode 100644 (file)
index 0000000..7cdb4b4
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "common/utils/dynamic_lib_handle.h"
+
+#include <memory>
+
+namespace common_installer {
+
+DynamicLibHandle::DynamicLibHandle() : lib_handle_(nullptr) {}
+
+std::unique_ptr<DynamicLibHandle> DynamicLibHandle::Create(
+    const boost::filesystem::path& path, int flags) {
+  std::unique_ptr<DynamicLibHandle> new_handle(new DynamicLibHandle);
+  if (!new_handle->CreateImpl(path, flags)) {
+    return nullptr;
+  }
+  return new_handle;
+}
+
+bool DynamicLibHandle::CreateImpl(const boost::filesystem::path& path,
+                                  int flags) {
+  lib_handle_ = dlopen(path.c_str(), flags);
+  if (!lib_handle_) {
+    LOG(ERROR) << "Failed to open library: " << path << " (" << dlerror()
+               << ")";
+    return false;
+  }
+  return true;
+}
+
+void* DynamicLibHandle::GetSymbol(const std::string& name) {
+  return dlsym(lib_handle_, name.c_str());
+}
+
+DynamicLibHandle::~DynamicLibHandle() { dlclose(lib_handle_); }
+
+}  // namespace common_installer
diff --git a/src/common/utils/dynamic_lib_handle.h b/src/common/utils/dynamic_lib_handle.h
new file mode 100644 (file)
index 0000000..0dbafc7
--- /dev/null
@@ -0,0 +1,54 @@
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_UTILS_DYNAMIC_LIB_HANDLE_H_
+#define COMMON_UTILS_DYNAMIC_LIB_HANDLE_H_
+
+#include <boost/filesystem/path.hpp>
+
+#include <dlfcn.h>
+#include <manifest_parser/utils/logging.h>
+
+#include <memory>
+#include <string>
+
+namespace common_installer {
+
+class DynamicLibHandle {
+ public:
+  static std::unique_ptr<DynamicLibHandle> Create(
+      const boost::filesystem::path& path, int flags);
+
+  template <typename Ret, typename... Args>
+  bool run(const std::string& name, Ret* result, Args&&... args) {
+    using PluginFunctionPtr = Ret (*)(Args...);
+    auto function = reinterpret_cast<PluginFunctionPtr>(GetSymbol(name));
+
+    if (!function) {
+      LOG(ERROR) << "Failed to get symbol: " << name <<" (" << dlerror() << ")";
+      return false;
+    }
+
+    *result = function(std::forward<Args>(args)...);
+    return true;
+  }
+
+  DynamicLibHandle(DynamicLibHandle&&) = default;
+  DynamicLibHandle& operator=(DynamicLibHandle&&) = default;
+
+  ~DynamicLibHandle();
+
+  SCOPE_LOG_TAG(DynamicLibHandle)
+
+ private:
+  DynamicLibHandle();
+  bool CreateImpl(const boost::filesystem::path& path, int flags);
+
+  void* GetSymbol(const std::string& name);
+  void* lib_handle_;
+};
+
+}  // namespace common_installer
+
+#endif  // COMMON_UTILS_DYNAMIC_LIB_HANDLE_H_