14#include "keyple/core/service/SmartCardServiceAdapter.hpp"
22#include "keyple/core/common/CommonApiProperties.hpp"
23#include "keyple/core/plugin/PluginApiProperties.hpp"
24#include "keyple/core/plugin/PluginIOException.hpp"
25#include "keyple/core/plugin/spi/AutonomousObservablePluginSpi.hpp"
26#include "keyple/core/plugin/spi/ObservablePluginSpi.hpp"
27#include "keyple/core/plugin/spi/PluginSpi.hpp"
28#include "keyple/core/plugin/spi/PoolPluginSpi.hpp"
29#include "keyple/core/service/AutonomousObservableLocalPluginAdapter.hpp"
30#include "keyple/core/service/KeyplePluginException.hpp"
31#include "keyple/core/service/LocalPoolPluginAdapter.hpp"
32#include "keyple/core/service/ObservableLocalPluginAdapter.hpp"
33#include "keyple/core/service/ReaderApiFactoryAdapter.hpp"
34#include "keyple/core/util/KeypleAssert.hpp"
35#include "keyple/core/util/cpp/KeypleStd.hpp"
36#include "keyple/core/util/cpp/StringUtils.hpp"
37#include "keyple/core/util/cpp/exception/IllegalArgumentException.hpp"
38#include "keyple/core/util/cpp/exception/IllegalStateException.hpp"
39#include "keyple/core/util/cpp/exception/PatternSyntaxException.hpp"
40#include "keypop/card/CardApiProperties.hpp"
41#include "keypop/reader/ReaderApiProperties.hpp"
47using keyple::core::common::CommonApiProperties_VERSION;
48using keyple::core::plugin::PluginApiProperties_VERSION;
49using keyple::core::plugin::PluginIOException;
50using keyple::core::plugin::spi::AutonomousObservablePluginSpi;
51using keyple::core::plugin::spi::ObservablePluginSpi;
52using keyple::core::plugin::spi::PluginSpi;
53using keyple::core::plugin::spi::PoolPluginSpi;
54using keyple::core::service::AutonomousObservableLocalPluginAdapter;
55using keyple::core::service::KeyplePluginException;
56using keyple::core::service::LocalPoolPluginAdapter;
57using keyple::core::service::ReaderApiFactoryAdapter;
58using keyple::core::util::Assert;
59using keyple::core::util::cpp::StringUtils;
60using keyple::core::util::cpp::exception::IllegalArgumentException;
61using keyple::core::util::cpp::exception::IllegalStateException;
62using keyple::core::util::cpp::exception::PatternSyntaxException;
63using keypop::card::CardApiProperties_VERSION;
64using keypop::reader::ReaderApiProperties_VERSION;
66const std::string SmartCardServiceAdapter::MSG_VERSION_MISMATCH_DETECTED
67 =
"Version mismatch detected: % '%' uses '%' version '%' (expected '%'). "
68 "Compatibility issues "
71std::shared_ptr<SmartCardServiceAdapter> SmartCardServiceAdapter::mInstance;
73SmartCardServiceAdapter::SmartCardServiceAdapter()
75 const char* value = std::getenv(
"isAutomaticStatusCodeHandlingEnabled");
77 && StringUtils::tolower(std::string(value)) ==
"false") {
78 mIsAutomaticStatusCodeHandlingEnabled =
false;
79 mLogger->warn(
"Automatic status code handling is disabled\n");
84SmartCardServiceAdapter::isAutomaticStatusCodeHandlingEnabled()
const
86 return mIsAutomaticStatusCodeHandlingEnabled;
89std::shared_ptr<SmartCardServiceAdapter>
90SmartCardServiceAdapter::getInstance()
92 if (mInstance ==
nullptr) {
93 mInstance = std::shared_ptr<SmartCardServiceAdapter>(
94 new SmartCardServiceAdapter());
101SmartCardServiceAdapter::compareVersions(
102 const std::string& providedVersion,
const std::string& localVersion)
const
104 const std::regex re(
"[.]");
106 std::vector<std::string> providedVersions;
107 std::split(providedVersion, re, std::back_inserter(providedVersions));
109 std::vector<std::string> localVersions;
110 std::split(localVersion, re, std::back_inserter(localVersions));
112 if (providedVersions.size() != localVersions.size()) {
113 throw IllegalStateException(
114 "Inconsistent version numbers. Provided = " + providedVersion
115 +
", Local: " + localVersion);
122 for (
const auto& v : providedVersions) {
123 provided += std::stoi(v);
126 for (
const auto& v : localVersions) {
127 local += std::stoi(v);
132 }
catch (
const std::invalid_argument&) {
133 throw IllegalStateException(
134 std::string(
"Bad version numbers: provided = ") + providedVersion
135 +
", local = " + localVersion);
139 return provided != local;
143SmartCardServiceAdapter::checkPluginVersion(
144 const std::shared_ptr<PluginFactorySpi> pluginFactorySpi)
147 pluginFactorySpi->getCommonApiVersion(),
148 CommonApiProperties_VERSION)
151 MSG_VERSION_MISMATCH_DETECTED,
152 std::string(
"plugin"),
153 pluginFactorySpi->getPluginName(),
154 std::string(
"Common API"),
155 pluginFactorySpi->getCommonApiVersion(),
156 CommonApiProperties_VERSION);
160 pluginFactorySpi->getPluginApiVersion(),
161 PluginApiProperties_VERSION)
164 MSG_VERSION_MISMATCH_DETECTED,
165 std::string(
"plugin"),
166 pluginFactorySpi->getPluginName(),
167 std::string(
"Plugin API"),
168 pluginFactorySpi->getPluginApiVersion(),
169 PluginApiProperties_VERSION);
173std::shared_ptr<Plugin>
174SmartCardServiceAdapter::registerPlugin(
175 const std::shared_ptr<KeyplePluginExtensionFactory> pluginFactory)
177 Assert::getInstance().notNull(pluginFactory,
"pluginFactory");
179 std::shared_ptr<AbstractPluginAdapter> plugin =
nullptr;
181 const std::lock_guard<std::mutex> lock(mMutex);
184 const auto factorySpi
185 = std::dynamic_pointer_cast<PluginFactorySpi>(pluginFactory);
187 = std::dynamic_pointer_cast<PoolPluginFactorySpi>(pluginFactory);
189 plugin = createLocalPlugin(factorySpi);
190 }
else if (poolSpi) {
191 plugin = createLocalPoolPlugin(poolSpi);
196 throw IllegalArgumentException(
198 "Cannot cast the provided factory to PluginFactorySpi, "
199 "PoolPluginFactorySpi or RemotePluginFactorySpi. Actual "
201 +
typeid(pluginFactory).name());
204 mPlugins.insert({plugin->getName(), plugin});
205 plugin->doRegister();
207 }
catch (
const IllegalArgumentException& e) {
208 throw IllegalArgumentException(
209 "The provided plugin factory doesn't implement the plugin"
213 }
catch (
const PluginIOException& e) {
214 throw KeyplePluginException(
215 std::string(
"Failed to register plugin: ") + plugin->getName(), e);
222SmartCardServiceAdapter::unregisterPlugin(
const std::string& pluginName)
224 mLogger->info(
"Unregistering plugin [plugin=%]\n", pluginName);
226 const std::lock_guard<std::mutex> lock(mMutex);
228 auto i = mPlugins.find(pluginName);
229 if (i != mPlugins.end()) {
230 std::shared_ptr<Plugin> removedPlugin = std::move(i->second);
231 std::dynamic_pointer_cast<AbstractPluginAdapter>(removedPlugin)
236 mLogger->warn(
"Plugin not registered [plugin=%]\n", pluginName);
240const std::vector<std::string>
241SmartCardServiceAdapter::getPluginNames()
const
243 std::vector<std::string> pluginNames;
244 for (
const auto& pair : mPlugins) {
245 pluginNames.push_back(pair.first);
251const std::vector<std::shared_ptr<Plugin>>
252SmartCardServiceAdapter::getPlugins()
const
254 std::vector<std::shared_ptr<Plugin>> plugins;
255 for (
const auto& pair : mPlugins) {
256 plugins.push_back(pair.second);
262std::shared_ptr<Plugin>
263SmartCardServiceAdapter::getPlugin(
const std::string& pluginName)
const
265 auto it = mPlugins.find(pluginName);
266 if (it != mPlugins.end()) {
273std::shared_ptr<Plugin>
274SmartCardServiceAdapter::getPlugin(
275 const std::shared_ptr<CardReader> cardReader)
const
277 for (
const auto& plugin : mPlugins) {
278 const auto& readers = plugin.second->getReaders();
282 [cardReader](
const std::shared_ptr<CardReader>& reader) {
283 return reader == cardReader;
285 return plugin.second;
292std::shared_ptr<CardReader>
293SmartCardServiceAdapter::getReader(
const std::string& readerName)
const
295 for (
const auto& plugin : mPlugins) {
296 const auto& readers = plugin.second->getReaders();
297 auto it = std::find_if(
300 [readerName](
const std::shared_ptr<CardReader>& reader) {
301 return reader->getName() == readerName;
303 if (it != readers.end()) {
311std::shared_ptr<CardReader>
312SmartCardServiceAdapter::findReader(
const std::string& readerNameRegex)
const
314 for (
const auto& plugin : mPlugins) {
315 std::shared_ptr<CardReader> reader(
316 plugin.second->findReader(readerNameRegex));
317 if (reader !=
nullptr) {
326SmartCardServiceAdapter::checkCardExtension(
327 const std::shared_ptr<KeypleCardExtension> cardExtension)
const
329 checkCardExtensionVersion(cardExtension);
332std::unique_ptr<ReaderApiFactory>
333SmartCardServiceAdapter::getReaderApiFactory()
335 return std::unique_ptr<ReaderApiFactoryAdapter>(
336 new ReaderApiFactoryAdapter());
340SmartCardServiceAdapter::checkPoolPluginVersion(
341 const std::shared_ptr<PoolPluginFactorySpi> poolPluginFactorySpi)
344 poolPluginFactorySpi->getCommonApiVersion(),
345 CommonApiProperties_VERSION)
348 MSG_VERSION_MISMATCH_DETECTED,
349 std::string(
"pool plugin"),
350 poolPluginFactorySpi->getPoolPluginName(),
351 std::string(
"Common API"),
352 poolPluginFactorySpi->getCommonApiVersion(),
353 CommonApiProperties_VERSION);
357 poolPluginFactorySpi->getPluginApiVersion(),
358 PluginApiProperties_VERSION)
361 MSG_VERSION_MISMATCH_DETECTED,
362 std::string(
"pool plugin"),
363 poolPluginFactorySpi->getPoolPluginName(),
364 std::string(
"Plugin API"),
365 poolPluginFactorySpi->getPluginApiVersion(),
366 PluginApiProperties_VERSION);
371SmartCardServiceAdapter::checkCardExtensionVersion(
372 const std::shared_ptr<KeypleCardExtension> cardExtension)
const
375 cardExtension->getCommonApiVersion(), CommonApiProperties_VERSION)
377 const auto& c = *cardExtension.get();
379 MSG_VERSION_MISMATCH_DETECTED,
380 std::string(
"card extension"),
381 std::string(
typeid(c).name()),
382 std::string(
"Common API"),
383 cardExtension->getCommonApiVersion(),
384 CommonApiProperties_VERSION);
388 cardExtension->getCardApiVersion(), CardApiProperties_VERSION)
390 const auto& c = *cardExtension.get();
392 MSG_VERSION_MISMATCH_DETECTED,
393 std::string(
"card extension"),
394 std::string(
typeid(c).name()),
395 std::string(
"Card API"),
396 cardExtension->getCardApiVersion(),
397 CardApiProperties_VERSION);
401 cardExtension->getReaderApiVersion(), ReaderApiProperties_VERSION)
403 const auto& c = *cardExtension.get();
405 MSG_VERSION_MISMATCH_DETECTED,
406 std::string(
"card extension"),
407 std::string(
typeid(c).name()),
408 std::string(
"Reader API"),
409 cardExtension->getReaderApiVersion(),
410 ReaderApiProperties_VERSION);
415SmartCardServiceAdapter::checkPluginRegistration(
const std::string& pluginName)
417 mLogger->info(
"Registering plugin [plugin=%]\n", pluginName);
419 const auto it = mPlugins.find(pluginName);
420 if (it != mPlugins.end()) {
421 throw IllegalStateException(
422 "Plugin '" + pluginName
423 +
"' has already been registered to the service");
427std::shared_ptr<AbstractPluginAdapter>
428SmartCardServiceAdapter::createLocalPlugin(
429 std::shared_ptr<PluginFactorySpi> pluginFactorySpi)
431 checkPluginRegistration(pluginFactorySpi->getPluginName());
432 checkPluginVersion(pluginFactorySpi);
434 std::shared_ptr<PluginSpi> pluginSpi = pluginFactorySpi->getPlugin();
436 if (pluginSpi->getName() != pluginFactorySpi->getPluginName()) {
437 throw IllegalArgumentException(
438 std::string(
"Plugin name '") + pluginSpi->getName()
439 +
"' mismatches the expected name '"
440 + pluginFactorySpi->getPluginName() +
"' provided by the factory");
443 std::shared_ptr<AbstractPluginAdapter> plugin =
nullptr;
445 auto observable = std::dynamic_pointer_cast<ObservablePluginSpi>(pluginSpi);
447 plugin = std::make_shared<ObservableLocalPluginAdapter>(observable);
450 = std::dynamic_pointer_cast<AutonomousObservablePluginSpi>(
453 plugin = std::make_shared<AutonomousObservableLocalPluginAdapter>(
456 plugin = std::make_shared<LocalPluginAdapter>(pluginSpi);
463std::shared_ptr<AbstractPluginAdapter>
464SmartCardServiceAdapter::createLocalPoolPlugin(
465 std::shared_ptr<PoolPluginFactorySpi> poolPluginFactorySpi)
467 checkPluginRegistration(poolPluginFactorySpi->getPoolPluginName());
468 checkPoolPluginVersion(poolPluginFactorySpi);
470 std::shared_ptr<PoolPluginSpi> poolPluginSpi
471 = poolPluginFactorySpi->getPoolPlugin();
473 if (poolPluginSpi->getName() != poolPluginFactorySpi->getPoolPluginName()) {
474 throw IllegalArgumentException(
475 std::string(
"Pool plugin name '") + poolPluginSpi->getName()
476 +
"' mismatches the expected name '"
477 + poolPluginFactorySpi->getPoolPluginName()
478 +
"' provided by the factory");
481 return std::make_shared<LocalPoolPluginAdapter>(poolPluginSpi);