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) {
+PluginsLauncher::Error PluginsLauncher::LaunchPlugin(
+ const boost::filesystem::path& plugin_path, xmlDocPtr docPtr,
+ ActionType action, const std::string& pkgId, int* result) {
+ LOG(DEBUG) << "Loading plugin: " << plugin_path;
+
+ DynamicLibHandle dlh;
+
+ if (!dlh.Create(plugin_path, RTLD_LAZY | RTLD_LOCAL)) {
LOG(ERROR) << "Failed to create library handle";
- return false;
+ return Error::FailedLibHandle;
}
- if (!RunPluginFunction(dl_handle.get(), ProcessType::PreInstall, action,
- pkgId.c_str(), result)) {
- LOG(ERROR) << "Preinstall failed";
- return false;
+ bool is_supported = false;
+
+ if (ExecPlugin(dlh, ProcessType::PreInstall, action, pkgId.c_str(),
+ result)) {
+ is_supported = true;
}
- if (!RunPluginFunction(dl_handle.get(), ProcessType::Install, action,
- docPtr, pkgId.c_str(), result)) {
- LOG(ERROR) << "Install failed";
- return false;
+ if (ExecPlugin(dlh, ProcessType::Install, action, docPtr, pkgId.c_str(),
+ result)) {
+ is_supported = true;
}
- if (!RunPluginFunction(dl_handle.get(), ProcessType::PostInstall, action,
- pkgId.c_str(), result)) {
- LOG(ERROR) << "Postinstall failed";
- return false;
+
+ if (ExecPlugin(dlh, ProcessType::PostInstall, action, pkgId.c_str(),
+ result)) {
+ is_supported = true;
}
- return true;
+
+ if (!is_supported) {
+ return Error::ActionNotSupported;
+ }
+
+ return Error::Success;
}
-bool PluginsLauncher::GetName(ProcessType process, ActionType action,
+bool PluginsLauncher::FunctionName(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::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
+ {{ActionType::Uninstall, ProcessType::PostInstall}, "PKGMGR_PARSER_PLUGIN_POST_UNINSTALL"} // NOLINT
};
auto pos = names.find(std::make_pair(action, process));
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::ExecPlugin(DynamicLibHandle& dlh, ProcessType process,
+ ActionType action, const char* pkgId,
+ int* result) {
+ return ExecPluginImpl(dlh, 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);
+bool PluginsLauncher::ExecPlugin(DynamicLibHandle& dlh, ProcessType process,
+ ActionType action, xmlDocPtr docPtr,
+ const char* pkgId, int* result) {
+ return ExecPluginImpl(dlh, process, action, result, docPtr, pkgId);
}
} // namespace common_installer
#include <string>
#include <memory>
-#include "utils/dynamic_lib_handle.h"
+#include "common/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);
+ enum class Error { Success, FailedLibHandle, ActionNotSupported };
+
+ Error 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 FunctionName(ProcessType process, ActionType action,
+ std::string* result);
- bool RunPluginFunction(DynamicLibHandle* dl_handle, ProcessType process,
- ActionType action, const char *pkgId, int *result);
+ bool ExecPlugin(DynamicLibHandle& dlh, 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);
+ bool ExecPlugin(DynamicLibHandle& dlh, 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) {
+ bool ExecPluginImpl(DynamicLibHandle& dlh, ProcessType process,
+ ActionType action, int* result, Args&&... args) {
std::string name;
- if (!GetName(process, action, &name)) {
+ if (!FunctionName(process, action, &name)) {
LOG(ERROR) << "Error during getting function name";
return false;
}
- return dl_handle->run(name, result, std::forward<Args>(args)...);
+ return dlh.Exec(name, result, std::forward<Args>(args)...);
}
SCOPE_LOG_TAG(PluginsLauncher)
-flag="0x00000001";type="tag";name="shortcut-list";path="/usr/etc/package-manager/parserlib/libshortcut-list.so"
-flag="0x00000002";type="tag";name="account";path="/usr/etc/package-manager/parserlib/libaccount.so"
-flag="0x00000004";type="tag";name="notifications";path="/usr/etc/package-manager/parserlib/libnotifications.so"
-flag="0x00000008";type="tag";name="privileges";path="/usr/etc/package-manager/parserlib/libprivileges.so"
-flag="0x00000010";type="tag";name="ime";path="/usr/etc/package-manager/parserlib/libime.so"
+flag="0x00000001";type="tag";name="shortcut-list";path="/etc/package-manager/parserlib/libshortcut-list.so"
+flag="0x00000002";type="tag";name="account";path="/etc/package-manager/parserlib/libaccount.so"
+flag="0x00000004";type="tag";name="notifications";path="/etc/package-manager/parserlib/libnotifications.so"
+flag="0x00000008";type="tag";name="privileges";path="/etc/package-manager/parserlib/libprivileges.so"
+flag="0x00000010";type="tag";name="ime";path="/etc/package-manager/parserlib/libime.so"
flag="0x00000020";type="category";name="http://tizen.org/category/downloadable_font";path="/usr/etc/package-manager/parserlib/category/libdownloadable_font.so"
flag="0x00000040";type="metadata";name="http://developer.samsung.com/tizen/metadata/sticker";path="/usr/etc/package-manager/parserlib/metadata/libsticker.so"
flag="0x00000080";type="metadata";name="http://developer.samsung.com/tizen/metadata/ttsengine";path="/usr/etc/package-manager/parserlib/metadata/libttsengine.so"
flag="0x00000400";type="category";name="http://tizen.org/category/antivirus";path="/usr/etc/package-manager/parserlib/category/libantivirus.so"
flag="0x00000800";type="metadata";name="http://developer.samsung.com/tizen/metadata/profile";path="/usr/etc/package-manager/parserlib/metadata/libtheme.so"
flag="0x00001000";type="category";name="http://tizen.org/category/tts";path="/usr/etc/package-manager/parserlib/category/libsamsung_tts.so"
-flag="0x00002000";type="tag";name="livebox";path="/usr/etc/package-manager/parserlib/liblivebox.so"
-flag="0x00004000";type="tag";name="watch-application";path="/usr/etc/package-manager/parserlib/libwatch-application.so"
-flag="0x00008000";type="tag";name="widget-application";path="/usr/etc/package-manager/parserlib/libwidget-application.so"
+flag="0x00002000";type="tag";name="livebox";path="/etc/package-manager/parserlib/liblivebox.so"
+flag="0x00004000";type="tag";name="watch-application";path="/etc/package-manager/parserlib/libwatch-application.so"
+flag="0x00008000";type="tag";name="widget-application";path="/etc/package-manager/parserlib/libwidget-application.so"
namespace common_installer {
namespace pkgmgr {
-StepRunParserPlugin::StepRunParserPlugin(InstallerContext* context,
- ActionType action_type)
+StepRunParserPlugin::StepRunParserPlugin(
+ InstallerContext* context, PluginsLauncher::ActionType action_type)
: Step(context), action_type_(action_type) {}
-Step::Status StepRunParserPlugin::ProcessingPlugins(
+Step::Status StepRunParserPlugin::ProcessPlugins(
const boost::filesystem::path& xml_path) {
// PLUGINS_LIST_FILE_PATH path generated from cmake
const std::string listPath(PLUGINS_LIST_INSTALL_FILE_PATH);
return Status::ERROR;
}
- std::vector<std::shared_ptr<PluginInfo>> plugins =
- plugin_manager_->UnknownTagList();
+ const PluginManager::TagList& plugins = plugin_manager_->UnknownTagList();
for (const std::shared_ptr<PluginInfo>& plugin : plugins) {
- if (!plugin_manager_->Launch(plugin->path(), action_type_,
+ if (!plugin_manager_->Launch(plugin->path(), plugin->name(), action_type_,
context_->pkgid.get())) {
LOG(ERROR) << "Error during launch tag name: " << plugin->name()
<< " path: " << plugin->path();
- return Status::ERROR;
- }
- // add plugin to array for undo process
- if (action_type_ == ActionType::Install) {
- installed_plugins_.push_back(plugin);
+ // some plugins do not have all methods, so no return error (skip error)
+ } else {
+ // add plugin to array for undo process
+ if (action_type_ == PluginsLauncher::ActionType::Install) {
+ installed_plugins_.push_back(plugin);
+ }
}
}
}
Step::Status StepRunParserPlugin::process() {
- return ProcessingPlugins(context_->xml_path.get());
+ return ProcessPlugins(context_->xml_path.get());
}
Step::Status StepRunParserPlugin::undo() {
- if (action_type_ == ActionType::Install) {
- if (installed_plugins_.empty()) {
- // no installed plugins
- return Status::OK;
- }
+ switch (action_type_) {
+ case PluginsLauncher::ActionType::Install: {
+ if (installed_plugins_.empty()) {
+ // no installed plugins
+ return Status::OK;
+ }
- for (const std::shared_ptr<PluginInfo>& plugin : installed_plugins_) {
- if (!plugin_manager_->Launch(plugin->path(), ActionType::Uninstall,
- context_->pkgid.get())) {
- LOG(ERROR) << "Error during uninstall tag name: " << plugin->name()
- << " path: " << plugin->path();
+ for (const std::shared_ptr<PluginInfo>& plugin : installed_plugins_) {
+ if (!plugin_manager_->Launch(plugin->path(), plugin->name(),
+ PluginsLauncher::ActionType::Uninstall,
+ context_->pkgid.get())) {
+ LOG(ERROR) << "Error during uninstall tag name: " << plugin->name()
+ << " path: " << plugin->path();
+ }
}
+ return Status::OK;
}
- } else if (action_type_ == ActionType::Upgrade) {
- return ProcessingPlugins(context_->backup_xml_path.get());
- } else if (action_type_ == ActionType::Uninstall) {
- return ProcessingPlugins(context_->xml_path.get());
+ case PluginsLauncher::ActionType::Upgrade:
+ return ProcessPlugins(context_->backup_xml_path.get());
+ case PluginsLauncher::ActionType::Uninstall:
+ return ProcessPlugins(context_->xml_path.get());
+ default:
+ return Status::ERROR;
}
- return Status::OK;
+
+ // never happen only to avoid compilation warning
+ return Status::ERROR;
}
} // namespace pkgmgr
class StepRunParserPlugin : public Step {
public:
explicit StepRunParserPlugin(InstallerContext* context,
- ActionType action_type);
+ PluginsLauncher::ActionType action_type);
Step::Status process() override;
Step::Status clean() { return Status::OK; }
SCOPE_LOG_TAG(RunParserPlugin)
private:
- Step::Status ProcessingPlugins(const boost::filesystem::path& xml_path);
- ActionType action_type_;
+ Step::Status ProcessPlugins(const boost::filesystem::path& xml_path);
+ PluginsLauncher::ActionType action_type_;
std::vector<std::shared_ptr<PluginInfo>> installed_plugins_;
std::unique_ptr<PluginManager> plugin_manager_;
};
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;
+bool DynamicLibHandle::Create(const boost::filesystem::path& path, int flags) {
+ if (lib_handle_) {
+ return true;
}
- 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 dlsym(lib_handle_, name.c_str());
}
-DynamicLibHandle::~DynamicLibHandle() { dlclose(lib_handle_); }
+DynamicLibHandle::~DynamicLibHandle() {
+ if (lib_handle_) {
+ dlclose(lib_handle_);
+ }
+}
} // namespace common_installer
class DynamicLibHandle {
public:
- static std::unique_ptr<DynamicLibHandle> Create(
- const boost::filesystem::path& path, int flags);
+ DynamicLibHandle();
+ bool Create(const boost::filesystem::path& path, int flags);
template <typename Ret, typename... Args>
- bool run(const std::string& name, Ret* result, Args&&... args) {
+ bool Exec(const std::string& name, Ret* result, Args... args) {
using PluginFunctionPtr = Ret (*)(Args...);
- auto function = reinterpret_cast<PluginFunctionPtr>(GetSymbol(name));
+ PluginFunctionPtr function =
+ reinterpret_cast<PluginFunctionPtr>(GetSymbol(name));
if (!function) {
- LOG(ERROR) << "Failed to get symbol: " << name <<" (" << dlerror() << ")";
+ LOG(WARNING) << "Failed to get symbol: " << name << " (" << dlerror()
+ << ")";
return false;
}
- *result = function(std::forward<Args>(args)...);
+ LOG(DEBUG) << "Execute plugin function: " << name << "...";
+ *result = function(args...);
return true;
}
DynamicLibHandle(DynamicLibHandle&&) = default;
DynamicLibHandle& operator=(DynamicLibHandle&&) = default;
- ~DynamicLibHandle();
+ virtual ~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_;
};
return true;
}
-const std::vector<std::shared_ptr<PluginInfo>>&
-PluginsListParser::PluginInfoList() {
+const PluginsListParser::PluginList& PluginsListParser::PluginInfoList() {
return plugin_info_list_;
}
/** this class parse plugin file */
class PluginsListParser {
public:
+ using PluginList = std::vector<std::shared_ptr<PluginInfo>>;
explicit PluginsListParser(const std::string& path) : path_(path) {}
bool Parse();
- const std::vector<std::shared_ptr<PluginInfo>>& PluginInfoList();
+ const PluginList& PluginInfoList();
private:
enum Column { Flag, Type, Name, Path };
return false;
}
- const std::vector<std::shared_ptr<PluginInfo>> pluginInfoList =
+ const PluginsListParser::PluginList& pluginInfoList =
list_parser_.PluginInfoList();
for (std::shared_ptr<PluginInfo> pluginInfo : pluginInfoList) {
return true;
}
-const std::vector<std::shared_ptr<PluginInfo>>&
-PluginManager::UnknownTagList() {
- return tags_;
+const PluginManager::TagList& PluginManager::UnknownTagList() { return tags_; }
+
+xmlDocPtr PluginManager::CreateDocPtrForPlugin(xmlDocPtr doc_ptr,
+ const std::string& tag_name) const {
+ // Make copy of document and root node
+ xmlNodePtr root_node = xmlDocGetRootElement(doc_ptr);
+ if (!root_node) {
+ LOG(ERROR) << "Original document is empty. Cannot create copy for plugin";
+ return nullptr;
+ }
+ xmlDocPtr plugin_doc_ptr = xmlCopyDoc(doc_ptr, 0);
+ xmlNodePtr plugin_root_node = xmlCopyNode(root_node, 0);
+ xmlDocSetRootElement(plugin_doc_ptr, plugin_root_node);
+
+ // Append elements that matches the tag name to new doc
+ for (xmlNodePtr child = xmlFirstElementChild(root_node);
+ child != nullptr; child = xmlNextElementSibling(child)) {
+ if (tag_name == reinterpret_cast<const char*>(child->name)) {
+ xmlAddChild(plugin_root_node, xmlCopyNode(child, 1));
+ }
+ }
+ xmlSetTreeDoc(plugin_root_node, plugin_doc_ptr);
+ return plugin_doc_ptr;
}
bool PluginManager::Launch(const boost::filesystem::path& plugin_path,
- ActionType action_type, const std::string& pkg_Id) {
- // TODO(l.wartalowic) add implementation
+ const std::string& tag_name,
+ PluginsLauncher::ActionType action_type,
+ const std::string& pkg_Id) {
LOG(INFO) << "Launching plugin path:" << plugin_path << " pkgId: " << pkg_Id;
- (void)plugin_path;
- (void)action_type;
- (void)pkg_Id;
- return true;
+
+ int result = EPERM;
+
+ xmlDocPtr plugin_doc_ptr = CreateDocPtrForPlugin(xml_parser_.doc_ptr(),
+ tag_name);
+ if (!plugin_doc_ptr)
+ return false;
+ PluginsLauncher::Error error = plugins_launcher_.LaunchPlugin(
+ plugin_path, plugin_doc_ptr, action_type, pkg_Id, &result);
+ xmlFreeDoc(plugin_doc_ptr);
+
+ switch (error) {
+ case PluginsLauncher::Error::Success: {
+ if (result != 0) {
+ LOG(ERROR) << "Error from plugin lib: " << plugin_path
+ << " error code: " << result;
+ return false;
+ }
+ return true;
+ }
+ case PluginsLauncher::Error::ActionNotSupported:
+ return true;
+
+ case PluginsLauncher::Error::FailedLibHandle:
+ default:
+ return false;
+ }
}
} // namespace common_installer
#include "common/utils/plugin_xml_parser.h"
#include "common/utils/plugin_list_parser.h"
+#include "common/plugins_launcher.h"
namespace common_installer {
-enum class ActionType { Install, Upgrade, Uninstall };
-
/** this class manages XML and plugin lists */
class PluginManager {
public:
+ using TagList = std::vector<std::shared_ptr<PluginInfo>>;
PluginManager(const std::string& xml_path, const std::string& list_path)
: xml_parser_(xml_path), list_parser_(list_path) {}
bool GenerateUnknownTagList();
- const std::vector<std::shared_ptr<PluginInfo>>& UnknownTagList();
- bool Launch(const boost::filesystem::path& pluginPath, ActionType actionType,
- const std::string& pkgId);
+ const TagList& UnknownTagList();
+ bool Launch(const boost::filesystem::path& pluginPath,
+ const std::string& tag_name,
+ PluginsLauncher::ActionType actionType, const std::string& pkgId);
private:
+ /**
+ * @brief CreateDocPtrForPlugin
+ * Create copy of xml document with nodes only matching requested
+ * tag_name
+ * @param doc_ptr original doc ptr of document
+ * @param tag_name name of required node/nodes
+ * @return requested copy
+ */
+ xmlDocPtr CreateDocPtrForPlugin(xmlDocPtr doc_ptr,
+ const std::string& tag_name) const;
+
std::vector<std::shared_ptr<PluginInfo>> tags_;
PluginsXmlParser xml_parser_;
PluginsListParser list_parser_;
+ PluginsLauncher plugins_launcher_;
};
} // namespace common_installer
return false;
}
+ doc_ptr_ = xmlReadFile(path_.c_str(), nullptr, 0);
+ if (!doc_ptr_) {
+ return false;
+ }
+
WrapperXMLReader obj_reader;
- xmlTextReaderPtr reader = obj_reader.Create(path_.c_str());
+ xmlTextReaderPtr reader = obj_reader.Create(doc_ptr_);
if (!reader) {
return false;
tags_.assign(tags.begin(), tags.end());
- // get here, after end of a "reading" file
- doc_ptr_ = xmlTextReaderCurrentDoc(reader);
-
- if (!doc_ptr_) {
- return false;
- }
-
return true;
}
public:
WrapperXMLReader() : reader_(nullptr) {}
- xmlTextReaderPtr Create(const std::string& path) {
- reader_ = xmlReaderForFile(path.c_str(), nullptr, 0);
+ xmlTextReaderPtr Create(const xmlDocPtr doc_ptr_) {
+ reader_ = xmlReaderWalker(doc_ptr_);
return reader_;
}
virtual ~WrapperXMLReader() {