14#include "keyple/core/service/resource/CardResourceServiceAdapter.hpp"
18#include "keyple/core/service/ObservablePlugin.hpp"
19#include "keyple/core/service/SmartCardServiceProvider.hpp"
20#include "keyple/core/service/resource/CardProfileManagerAdapter.hpp"
21#include "keyple/core/util/HexUtil.hpp"
22#include "keyple/core/util/KeypleAssert.hpp"
23#include "keyple/core/util/cpp/System.hpp"
24#include "keyple/core/util/cpp/exception/IllegalStateException.hpp"
25#include "keypop/reader/CardReader.hpp"
32using keyple::core::service::ObservablePlugin;
33using keyple::core::service::SmartCardServiceProvider;
34using keyple::core::util::HexUtil;
35using keyple::core::util::cpp::System;
36using keyple::core::util::cpp::exception::IllegalStateException;
37using keypop::reader::CardReader;
39std::shared_ptr<CardResourceServiceAdapter>
40 CardResourceServiceAdapter::mInstance;
42std::shared_ptr<CardResourceServiceAdapter>
43CardResourceServiceAdapter::getInstance()
45 if (mInstance ==
nullptr) {
46 mInstance = std::make_shared<CardResourceServiceAdapter>();
53CardResourceServiceAdapter::getCardResourceInfo(
54 const std::shared_ptr<CardResource> cardResource)
63std::shared_ptr<ReaderManagerAdapter>
64CardResourceServiceAdapter::getReaderManager(
65 const std::shared_ptr<CardReader> reader)
const
67 const auto it = mReaderToReaderManagerMap.find(reader);
68 if (it != mReaderToReaderManagerMap.end()) {
76CardResourceServiceAdapter::registerPoolCardResource(
77 std::shared_ptr<CardResource> cardResource,
78 std::shared_ptr<PoolPlugin> poolPlugin)
80 mCardResourceToPoolPluginMap.insert({cardResource, poolPlugin});
84CardResourceServiceAdapter::configure(
85 std::shared_ptr<CardResourceServiceConfiguratorAdapter> configurator)
87 mLogger->info(
"Applying new card resource service configuration\n");
91 mConfigurator = configurator;
94 mConfigurator = configurator;
97 mLogger->info(
"New card resource service configuration applied\n");
100std::shared_ptr<CardResourceServiceConfigurator>
101CardResourceServiceAdapter::getConfigurator()
const
103 return std::make_shared<CardResourceServiceConfiguratorAdapter>();
107CardResourceServiceAdapter::start()
109 if (mConfigurator ==
nullptr) {
110 throw IllegalStateException(
111 "The card resource service is not configured");
118 mLogger->info(
"Starting card resource service\n");
120 initializeReaderManagers();
121 initializeCardProfileManagers();
122 removeUnusedReaderManagers();
126 mLogger->info(
"Card resource service started\n");
130CardResourceServiceAdapter::stop()
136 mReaderToReaderManagerMap.clear();
137 mCardProfileNameToCardProfileManagerMap.clear();
138 mCardResourceToPoolPluginMap.clear();
139 mPluginToObservableReadersMap.clear();
141 mLogger->info(
"Card resource service stopped\n");
144std::shared_ptr<CardResource>
145CardResourceServiceAdapter::getCardResource(
146 const std::string& cardResourceProfileName)
const
149 "Searching available card resource [profile=%]\n",
150 cardResourceProfileName);
153 throw IllegalStateException(
"Card resource service not started");
156 Assert::getInstance().notEmpty(
157 cardResourceProfileName,
"cardResourceProfileName");
159 std::shared_ptr<CardProfileManagerAdapter> cardProfileManager =
nullptr;
161 = mCardProfileNameToCardProfileManagerMap.find(cardResourceProfileName);
162 if (it != mCardProfileNameToCardProfileManagerMap.end()) {
163 cardProfileManager = it->second;
166 Assert::getInstance().notNull(
167 cardProfileManager,
"cardResourceProfileName");
169 std::shared_ptr<CardResource> cardResource
170 = cardProfileManager->getCardResource();
173 "Card resource found [cardResource=%]\n",
174 getCardResourceInfo(cardResource));
180CardResourceServiceAdapter::releaseCardResource(
181 std::shared_ptr<CardResource> cardResource)
184 "Releasing card resource [cardResource=%]\n",
185 getCardResourceInfo(cardResource));
188 throw IllegalStateException(
"Card resource service not started");
191 Assert::getInstance().notNull(cardResource,
"cardResource");
194 std::shared_ptr<ReaderManagerAdapter> readerManager =
nullptr;
196 const auto reader = cardResource->getReader();
197 if (reader ==
nullptr) {
198 throw IllegalArgumentException(
"Invalid reader");
201 const auto it = mReaderToReaderManagerMap.find(reader);
202 if (it != mReaderToReaderManagerMap.end()) {
203 readerManager = it->second;
204 readerManager->unlock();
206 std::shared_ptr<PoolPlugin> poolPlugin =
nullptr;
207 const auto itt = mCardResourceToPoolPluginMap.find(cardResource);
208 if (itt != mCardResourceToPoolPluginMap.end()) {
209 poolPlugin = itt->second;
210 mCardResourceToPoolPluginMap.erase(cardResource);
211 poolPlugin->releaseReader(reader);
215 mLogger->debug(
"Card resource released\n");
219CardResourceServiceAdapter::removeCardResource(
220 std::shared_ptr<CardResource> cardResource)
222 releaseCardResource(cardResource);
225 std::shared_ptr<ReaderManagerAdapter> readerManager =
nullptr;
228 = std::dynamic_pointer_cast<CardReader>(cardResource->getReader());
230 throw IllegalArgumentException(
"Invalid reader");
233 const auto it = mReaderToReaderManagerMap.find(r);
234 if (it != mReaderToReaderManagerMap.end()) {
235 readerManager = it->second;
236 readerManager->removeCardResource(cardResource);
238 for (
auto& pair : mCardProfileNameToCardProfileManagerMap) {
239 pair.second->removeCardResource(cardResource);
244 "Card resource removed [cardResource=%]\n",
245 getCardResourceInfo(cardResource));
249CardResourceServiceAdapter::onPluginEvent(
250 const std::shared_ptr<PluginEvent> pluginEvent)
256 std::shared_ptr<Plugin> plugin
257 = SmartCardServiceProvider::getService()->getPlugin(
258 pluginEvent->getPluginName());
260 if (pluginEvent->getType() == PluginEvent::Type::READER_CONNECTED) {
261 for (
const std::string& readerName : pluginEvent->getReaderNames()) {
264 std::shared_ptr<CardReader> reader = plugin->getReader(readerName);
265 if (reader !=
nullptr) {
266 const std::lock_guard<std::mutex> lock(mMutex);
267 onReaderConnected(reader, plugin);
271 for (
const std::string& readerName : pluginEvent->getReaderNames()) {
276 std::shared_ptr<CardReader> reader = getReader(readerName);
277 if (reader !=
nullptr) {
279 const std::lock_guard<std::mutex> lock(mMutex);
280 onReaderDisconnected(reader, plugin);
287CardResourceServiceAdapter::onReaderEvent(
288 const std::shared_ptr<CardReaderEvent> readerEvent)
294 std::shared_ptr<CardReader> reader
295 = getReader(readerEvent->getReaderName());
296 if (reader !=
nullptr) {
298 const std::lock_guard<std::mutex> lock(mMutex);
299 const auto it = mReaderToReaderManagerMap.find(reader);
300 if (it != mReaderToReaderManagerMap.end()) {
301 onReaderEvent(readerEvent, it->second);
307CardResourceServiceAdapter::initializeReaderManagers()
309 for (
const auto& plugin : mConfigurator->getPlugins()) {
310 for (
const auto& reader : plugin->getReaders()) {
311 registerReader(reader, plugin);
316std::shared_ptr<ReaderManagerAdapter>
317CardResourceServiceAdapter::registerReader(
318 std::shared_ptr<CardReader> reader, std::shared_ptr<Plugin> plugin)
323 std::shared_ptr<ReaderConfiguratorSpi> readerConfiguratorSpi =
nullptr;
325 const auto& configuredPlugins = mConfigurator->getConfiguredPlugins();
326 const auto it = std::find_if(
327 configuredPlugins.begin(),
328 configuredPlugins.end(),
329 [plugin](
const std::shared_ptr<ConfiguredPlugin>& configuredPlugin) {
330 return configuredPlugin->getPlugin() == plugin;
333 readerConfiguratorSpi = it != configuredPlugins.end()
334 ? (*it)->getReaderConfiguratorSpi()
337 auto readerManager = std::make_shared<ReaderManagerAdapter>(
340 readerConfiguratorSpi,
341 mConfigurator->getUsageTimeoutMillis());
343 mReaderToReaderManagerMap.insert({reader, readerManager});
345 const auto observable
346 = std::dynamic_pointer_cast<ObservableCardReader>(reader);
348 const auto _it = mPluginToObservableReadersMap.find(plugin);
349 if (_it != mPluginToObservableReadersMap.end()) {
351 _it->second.push_back(observable);
354 std::vector<std::shared_ptr<ObservableCardReader>>
355 usedObservableReaders;
356 usedObservableReaders.push_back(observable);
357 mPluginToObservableReadersMap.insert(
358 {plugin, usedObservableReaders});
362 return readerManager;
366CardResourceServiceAdapter::initializeCardProfileManagers()
368 for (
const auto& profile :
369 mConfigurator->getCardResourceProfileConfigurators()) {
370 mCardProfileNameToCardProfileManagerMap.insert(
371 {profile->getProfileName(),
372 std::make_shared<CardProfileManagerAdapter>(
373 profile, mConfigurator)});
378CardResourceServiceAdapter::removeUnusedReaderManagers()
380 std::vector<std::shared_ptr<ReaderManagerAdapter>> readerManagers;
381 for (
const auto& pair : mReaderToReaderManagerMap) {
382 readerManagers.push_back(pair.second);
385 for (
const auto& readerManager : readerManagers) {
386 if (!readerManager->isActive()) {
388 readerManager->getReader(), readerManager->getPlugin());
394CardResourceServiceAdapter::unregisterReader(
395 std::shared_ptr<CardReader> reader, std::shared_ptr<Plugin> plugin)
397 mReaderToReaderManagerMap.erase(reader);
399 const auto it = mPluginToObservableReadersMap.find(plugin);
400 auto observableCardReader
401 = std::dynamic_pointer_cast<ObservableCardReader>(reader);
403 if (it != mPluginToObservableReadersMap.end()
404 && observableCardReader !=
nullptr) {
405 observableCardReader->removeObserver(shared_from_this());
408 it->second.begin(), it->second.end(), observableCardReader),
414CardResourceServiceAdapter::startMonitoring()
416 for (
auto& configuredPlugin : mConfigurator->getConfiguredPlugins()) {
417 auto observable = std::dynamic_pointer_cast<ObservablePlugin>(
418 configuredPlugin->getPlugin());
419 if (configuredPlugin->isWithPluginMonitoring()
420 && observable !=
nullptr) {
422 "Reader monitoring start requested [plugin=%]\n",
423 configuredPlugin->getPlugin()->getName());
424 startPluginObservation(configuredPlugin);
428 = mPluginToObservableReadersMap.find(configuredPlugin->getPlugin());
429 if (configuredPlugin->isWithReaderMonitoring()
430 && it != mPluginToObservableReadersMap.end()) {
431 for (
auto& reader : it->second) {
433 "Card monitoring start requested [reader=%]\n",
435 startReaderObservation(reader, configuredPlugin);
442CardResourceServiceAdapter::stopMonitoring()
444 for (
auto& configuredPlugin : mConfigurator->getConfiguredPlugins()) {
445 auto observable = std::dynamic_pointer_cast<ObservablePlugin>(
446 configuredPlugin->getPlugin());
447 if (configuredPlugin->isWithPluginMonitoring()
448 && observable !=
nullptr) {
450 "Reader monitoring stopped [plugin=%]\n",
451 configuredPlugin->getPlugin()->getName());
452 std::dynamic_pointer_cast<ObservablePlugin>(
453 configuredPlugin->getPlugin())
454 ->removeObserver(shared_from_this());
458 = mPluginToObservableReadersMap.find(configuredPlugin->getPlugin());
459 if (configuredPlugin->isWithReaderMonitoring()
460 && it != mPluginToObservableReadersMap.end()) {
461 for (
auto& reader : it->second) {
463 "Card monitoring stopped [reader=%]\n", reader->getName());
464 reader->removeObserver(shared_from_this());
470std::shared_ptr<CardReader>
471CardResourceServiceAdapter::getReader(
const std::string& readerName)
const
473 auto it = std::find_if(
474 mReaderToReaderManagerMap.begin(),
475 mReaderToReaderManagerMap.end(),
476 [readerName](
const std::pair<
477 std::shared_ptr<CardReader>,
478 std::shared_ptr<ReaderManagerAdapter>>& pair) {
479 return pair.first->getName() == readerName;
482 return (it != mReaderToReaderManagerMap.end()) ? (*it).first :
nullptr;
486CardResourceServiceAdapter::onReaderConnected(
487 std::shared_ptr<CardReader> reader, std::shared_ptr<Plugin> plugin)
489 std::shared_ptr<ReaderManagerAdapter> readerManager
490 = registerReader(reader, plugin);
491 for (
auto pair : mCardProfileNameToCardProfileManagerMap) {
492 pair.second->onReaderConnected(readerManager);
495 if (readerManager->isActive()) {
496 startMonitoring(reader, plugin);
498 unregisterReader(reader, plugin);
503CardResourceServiceAdapter::startMonitoring(
504 std::shared_ptr<CardReader> reader, std::shared_ptr<Plugin> plugin)
506 auto observable = std::dynamic_pointer_cast<ObservableCardReader>(reader);
507 if (observable !=
nullptr) {
508 for (
auto& configuredPlugin : mConfigurator->getConfiguredPlugins()) {
509 if (configuredPlugin->getPlugin() == plugin
510 && configuredPlugin->isWithReaderMonitoring()) {
512 "Card monitoring start requested [reader=%]\n",
514 startReaderObservation(observable, configuredPlugin);
521CardResourceServiceAdapter::startPluginObservation(
522 std::shared_ptr<ConfiguredPlugin> configuredPlugin)
524 auto observablePlugin = std::dynamic_pointer_cast<ObservablePlugin>(
525 configuredPlugin->getPlugin());
526 observablePlugin->setPluginObservationExceptionHandler(
527 configuredPlugin->getPluginObservationExceptionHandlerSpi());
528 observablePlugin->addObserver(shared_from_this());
532CardResourceServiceAdapter::startReaderObservation(
533 std::shared_ptr<ObservableCardReader> observableReader,
534 std::shared_ptr<ConfiguredPlugin> configuredPlugin)
536 observableReader->setReaderObservationExceptionHandler(
537 configuredPlugin->getReaderObservationExceptionHandlerSpi());
538 observableReader->addObserver(shared_from_this());
539 observableReader->startCardDetection(
540 ObservableCardReader::DetectionMode::REPEATING);
544CardResourceServiceAdapter::onReaderDisconnected(
545 std::shared_ptr<CardReader> reader, std::shared_ptr<Plugin> plugin)
547 const auto it = mReaderToReaderManagerMap.find(reader);
548 if (it != mReaderToReaderManagerMap.end()) {
550 "Removing disconnected reader and all associated card resources " \
554 onCardRemoved(it->second);
555 unregisterReader(reader, plugin);
560CardResourceServiceAdapter::onReaderEvent(
561 const std::shared_ptr<CardReaderEvent> readerEvent,
562 std::shared_ptr<ReaderManagerAdapter> readerManager)
564 if (readerEvent->getType() == CardReaderEvent::Type::CARD_INSERTED
565 || readerEvent->getType() == CardReaderEvent::Type::CARD_MATCHED) {
567 "Creating new card resources matching the new card inserted " \
569 readerManager->getReader()->getName());
571 onCardInserted(readerManager);
575 "Removing all card resources caused by a card removal or reader " \
576 "unregistration [reader=%]\n",
577 readerManager->getReader()->getName());
579 onCardRemoved(readerManager);
584CardResourceServiceAdapter::onCardInserted(
585 std::shared_ptr<ReaderManagerAdapter> readerManager)
587 for (
auto& pair : mCardProfileNameToCardProfileManagerMap) {
588 pair.second->onCardInserted(readerManager);
593CardResourceServiceAdapter::onCardRemoved(
594 std::shared_ptr<ReaderManagerAdapter> readerManager)
596 const std::vector<std::shared_ptr<CardResourceAdapter>>&
597 cardResourcesToRemove
598 = readerManager->getCardResources();
600 for (
const auto& cardResource : cardResourcesToRemove) {
601 removeCardResource(cardResource);