PageRenderTime 25ms CodeModel.GetById 0ms RepoModel.GetById 1ms app.codeStats 0ms

/src/common/plugin/PluginManager.cpp

https://gitlab.com/admin-github-cloud/cynara
C++ | 166 lines | 113 code | 28 blank | 25 comment | 24 complexity | 598f1f3c3cab9a12290995fb7c1c3437 MD5 | raw file
  1. /*
  2. * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /**
  17. * @file src/common/plugin/PluginManager.cpp
  18. * @author Zofia Abramowska <z.abramowska@samsung.com>
  19. * @author Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
  20. * @version 1.0
  21. * @brief Definition of PluginManager class
  22. */
  23. #define _BSD_SOURCE_
  24. #include <cinttypes>
  25. #include <cstdlib>
  26. #include <cstring>
  27. #include <dirent.h>
  28. #include <dlfcn.h>
  29. #include <functional>
  30. #include <attributes/attributes.h>
  31. #include <exceptions/UnknownPolicyTypeException.h>
  32. #include <log/log.h>
  33. #include "PluginManager.h"
  34. namespace {
  35. int pluginFilter(const struct dirent *ent) {
  36. #ifdef _DIRENT_HAVE_D_TYPE
  37. if (ent->d_type != DT_REG) {
  38. return 0;
  39. }
  40. #endif
  41. if (ent->d_name[0] == '.') {
  42. return 0;
  43. }
  44. return 1;
  45. }
  46. }
  47. namespace Cynara {
  48. PluginManager::PluginManager(const std::string &pluginDir) : m_dir(pluginDir) {
  49. }
  50. PluginManager::~PluginManager(void) {
  51. // We have to be sure, that external objects will be destroyed
  52. // before handles to libraries are closed.
  53. for (auto &plugin : m_plugins) {
  54. plugin.second.reset();
  55. }
  56. }
  57. ExternalPluginPtr PluginManager::getPlugin(PolicyType pType) {
  58. return m_plugins[pType];
  59. }
  60. std::vector<PolicyDescription> PluginManager::getPolicyDescriptions(void) const {
  61. std::vector<PolicyDescription> descriptions;
  62. descriptions.reserve(m_plugins.size());
  63. for (auto &plugin : m_plugins) {
  64. descriptions.push_back(plugin.first);
  65. }
  66. return descriptions;
  67. }
  68. void PluginManager::invalidateAll(void) {
  69. for (auto &plugin : m_plugins) {
  70. plugin.second->invalidate();
  71. }
  72. }
  73. void PluginManager::checkPolicyType(PolicyType pType) const {
  74. const auto it = m_plugins.find(pType);
  75. if (it == m_plugins.end() || it->second == nullptr)
  76. throw UnknownPolicyTypeException(pType);
  77. }
  78. void PluginManager::loadPlugins(void) {
  79. struct dirent **nameList = NULL;
  80. int fileAmount = scandir(m_dir.c_str(), &nameList, pluginFilter, alphasort);
  81. if (fileAmount < 0) {
  82. UNUSED int err = errno;
  83. LOGE("Couldn't scan for plugins in <%s> : <%s>", m_dir.c_str(), strerror(err));
  84. return;
  85. }
  86. std::unique_ptr<dirent*, std::function<void(dirent**)>> direntPtr(nameList,
  87. [fileAmount](dirent** dirs) {
  88. for (int i = 0; i < fileAmount; i++) {
  89. free(dirs[i]);
  90. }
  91. free(dirs);
  92. });
  93. for (int i = 0; i < fileAmount; i++) {
  94. openPlugin(m_dir + nameList[i]->d_name);
  95. }
  96. }
  97. void PluginManager::openPlugin(const std::string &path) {
  98. LOGD("Loading plugin: <%s>", path.c_str());
  99. void *handle = dlopen(path.c_str(), RTLD_LAZY);
  100. if (!handle) {
  101. LOGW("File could not be dlopened <%s> : <%s>", path.c_str(), dlerror());
  102. return;
  103. }
  104. PluginLibPtr handlePtr(handle, std::ptr_fun(dlclose));
  105. //Flush any previous errors
  106. dlerror();
  107. create_t creator = reinterpret_cast<create_t>(dlsym(handle, "create"));
  108. char *error;
  109. if ((error = dlerror()) != NULL) {
  110. LOGE("Couldn't resolve symbol <create> from lib <%s> : <%s>", path.c_str(), error);
  111. return;
  112. }
  113. destroy_t destroyer = reinterpret_cast<destroy_t>(dlsym(handle, "destroy"));
  114. if ((error = dlerror()) != NULL) {
  115. LOGE("Couldn't resolve symbol <destroy> from lib <%s> : <%s>", path.c_str(), error);
  116. return;
  117. }
  118. ExternalPluginPtr pluginPtr(creator(), destroyer);
  119. if (!pluginPtr) {
  120. LOGE("Couldn't create plugin for <%s>", path.c_str());
  121. return;
  122. }
  123. auto policies = pluginPtr->getSupportedPolicyDescr();
  124. if (policies.empty()) {
  125. LOGE("Plugin <%s> does not support any type!", path.c_str());
  126. return;
  127. }
  128. for (auto &desc : policies) {
  129. if (!m_plugins.insert(std::make_pair(desc, pluginPtr)).second) {
  130. LOGW("Policy: type [%" PRIu16 "] name <%s> was already supported.",
  131. desc.type, desc.name.c_str());
  132. } else {
  133. LOGD("Supported policy: type [%" PRIu16 "] name <%s>", desc.type, desc.name.c_str());
  134. }
  135. }
  136. m_pluginLibs.push_back(std::move(handlePtr));
  137. }
  138. } // namespace Cynara