Fcitx
addonloader.cpp
1 /*
2  * SPDX-FileCopyrightText: 2016-2016 CSSlayer <wengxt@gmail.com>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  */
7 
8 #include "addonloader.h"
9 #include <exception>
10 #include <filesystem>
11 #include <memory>
12 #include <string>
13 #include <string_view>
14 #include <utility>
15 #include <vector>
16 #include "fcitx-utils/flags.h"
17 #include "fcitx-utils/library.h"
18 #include "fcitx-utils/log.h"
21 #include "addoninfo.h"
22 #include "addoninstance.h"
23 #include "addonloader_p.h"
24 #include "config.h"
25 
26 namespace fcitx {
27 
28 AddonLoader::~AddonLoader() {}
29 
30 SharedLibraryLoader::~SharedLibraryLoader() {}
31 
32 AddonInstance *SharedLibraryLoader::load(const AddonInfo &info,
33  AddonManager *manager) {
34  auto iter = registry_.find(info.uniqueName());
35  if (iter == registry_.end()) {
36  std::vector<std::string> libnames =
37  stringutils::split(info.library(), ";");
38 
39  if (libnames.empty()) {
40  FCITX_ERROR() << "Failed to parse Library field: " << info.library()
41  << " for addon " << info.uniqueName();
42  return nullptr;
43  }
44 
45  std::vector<Library> libraries;
46  for (std::string_view libname : libnames) {
47  Flags<LibraryLoadHint> flag = LibraryLoadHint::DefaultHint;
48  if (stringutils::consumePrefix(libname, "export:")) {
49  flag |= LibraryLoadHint::ExportExternalSymbolsHint;
50  }
51  const auto file =
52  stringutils::concat(libname, FCITX_LIBRARY_SUFFIX);
53  const auto libraryPaths = StandardPaths::global().locateAll(
54  StandardPathsType::Addon, file);
55  if (libraryPaths.empty()) {
56  FCITX_ERROR() << "Could not locate library " << file
57  << " for addon " << info.uniqueName() << ".";
58  }
59  bool loaded = false;
60  for (const auto &libraryPath : libraryPaths) {
61  Library library(libraryPath);
62  if (library.load(flag)) {
63  libraries.push_back(std::move(library));
64  loaded = true;
65  break;
66  }
67  FCITX_ERROR()
68  << "Failed to load library for addon " << info.uniqueName()
69  << " on " << libraryPath << ". Error: " << library.error();
70  }
71  if (!loaded) {
72  break;
73  }
74  }
75 
76  if (libraries.size() == libnames.size()) {
77  try {
78  registry_.emplace(info.uniqueName(),
79  std::make_unique<SharedLibraryFactory>(
80  info, std::move(libraries)));
81  } catch (const std::exception &e) {
82  FCITX_ERROR() << "Failed to initialize addon factory for addon "
83  << info.uniqueName() << ". Error: " << e.what();
84  }
85  iter = registry_.find(info.uniqueName());
86  }
87  }
88 
89  if (iter == registry_.end()) {
90  return nullptr;
91  }
92 
93  try {
94  return iter->second->factory()->create(manager);
95  } catch (const std::exception &e) {
96  FCITX_ERROR() << "Failed to create addon: " << info.uniqueName() << " "
97  << e.what();
98  } catch (...) {
99  FCITX_ERROR() << "Failed to create addon: " << info.uniqueName();
100  }
101  return nullptr;
102 }
103 
104 StaticLibraryLoader::StaticLibraryLoader(StaticAddonRegistry *registry_)
105  : registry(registry_) {}
106 
107 AddonInstance *StaticLibraryLoader::load(const AddonInfo &info,
108  AddonManager *manager) {
109  auto iter = registry->find(info.uniqueName());
110  if (iter == registry->end()) {
111  return nullptr;
112  }
113  try {
114  return iter->second->create(manager);
115  } catch (const std::exception &e) {
116  FCITX_ERROR() << "Failed to create addon: " << info.uniqueName() << " "
117  << e.what();
118  } catch (...) {
119  FCITX_ERROR() << "Failed to create addon: " << info.uniqueName();
120  }
121  return nullptr;
122 }
123 } // namespace fcitx
static const StandardPaths & global()
Return the global instance of StandardPath.
std::vector< std::filesystem::path > locateAll(StandardPathsType type, const std::filesystem::path &path, StandardPathsModes modes=StandardPathsMode::Default) const
Check if path exists in all directories.
bool consumePrefix(std::string_view &str, std::string_view prefix)
Return a substring of input str if str starts with given prefix.
Definition: action.cpp:17
Class to handler dynamic library.
std::vector< std::string > split(std::string_view str, std::string_view delim, SplitBehavior behavior)
Split the string by delim.
New Utility classes to handle application specific path.
Addon For fcitx.
String handle utilities.
Helper template class to make easier to use type safe enum flags.
Log utilities.