14#include "keyple/core/service/resource/CardProfileManagerAdapter.hpp"
19#include "keyple/core/service/Plugin.hpp"
20#include "keyple/core/service/SmartCardServiceProvider.hpp"
21#include "keyple/core/service/resource/CardResourceServiceAdapter.hpp"
22#include "keyple/core/util/cpp/Arrays.hpp"
23#include "keyple/core/util/cpp/System.hpp"
24#include "keyple/core/util/cpp/Thread.hpp"
25#include "keyple/core/util/cpp/exception/IllegalStateException.hpp"
26#include "keyple/core/util/cpp/exception/InterruptedException.hpp"
33using keyple::core::service::Plugin;
34using keyple::core::service::SmartCardServiceProvider;
35using keyple::core::service::resource::CardResourceServiceAdapter;
36using keyple::core::util::cpp::Arrays;
37using keyple::core::util::cpp::System;
38using keyple::core::util::cpp::Thread;
39using keyple::core::util::cpp::exception::IllegalStateException;
40using keyple::core::util::cpp::exception::InterruptedException;
44CardProfileManagerAdapter::CardProfileManagerAdapter(
45 std::shared_ptr<CardResourceProfileConfigurator> cardProfile,
46 std::shared_ptr<CardResourceServiceConfiguratorAdapter> globalConfiguration)
47: mCardProfile(cardProfile)
48, mGlobalConfiguration(globalConfiguration)
49, mService(CardResourceServiceAdapter::getInstance())
52 if (cardProfile->getReaderNameRegex() !=
"") {
53 mReaderNameRegexPattern
54 = Pattern::compile(cardProfile->getReaderNameRegex());
56 mReaderNameRegexPattern =
nullptr;
60 if (cardProfile->getPlugins().empty()) {
61 initializeCardResourcesUsingDefaultPlugins();
63 initializeCardResourcesUsingProfilePlugins();
68CardProfileManagerAdapter::removeCardResource(
69 std::shared_ptr<CardResource> cardResource)
72 = std::find(mCardResources.begin(), mCardResources.end(), cardResource);
74 if (it != mCardResources.end()) {
75 mCardResources.erase(it);
80CardProfileManagerAdapter::onReaderConnected(
81 std::shared_ptr<ReaderManagerAdapter> readerManager)
83 if (mCardProfile->getPlugins().empty()) {
84 initializeCardResource(readerManager);
86 const auto& profilePlugins = mCardProfile->getPlugins();
87 const auto it = std::find_if(
88 profilePlugins.begin(),
90 [readerManager](
const std::shared_ptr<Plugin>& profilePlugin) {
91 return (profilePlugin == readerManager->getPlugin());
94 if (it != profilePlugins.end()) {
95 initializeCardResource(readerManager);
102CardProfileManagerAdapter::onCardInserted(
103 std::shared_ptr<ReaderManagerAdapter> readerManager)
105 onReaderConnected(readerManager);
108std::shared_ptr<CardResource>
109CardProfileManagerAdapter::getCardResource()
111 std::shared_ptr<CardResource> cardResource =
nullptr;
112 uint64_t maxTime = System::currentTimeMillis()
113 + mGlobalConfiguration->getTimeoutMillis();
116 if (mPlugins.empty()) {
117 cardResource = getPoolCardResource();
119 if (mPoolPlugins.empty()) {
120 cardResource = getRegularCardResource();
122 cardResource = getRegularOrPoolCardResource();
126 pauseIfNeeded(cardResource);
128 }
while (cardResource ==
nullptr
129 && mGlobalConfiguration->isBlockingAllocationMode()
130 && System::currentTimeMillis() <= maxTime);
136CardProfileManagerAdapter::initializeCardResourcesUsingProfilePlugins()
138 for (
const auto& plugin : mCardProfile->getPlugins()) {
139 const auto poolPlugin = std::dynamic_pointer_cast<PoolPlugin>(plugin);
141 mPoolPlugins.push_back(poolPlugin);
143 mPlugins.push_back(plugin);
144 initializeCardResources(plugin);
150CardProfileManagerAdapter::initializeCardResourcesUsingDefaultPlugins()
152 const auto& poolPlugins = mGlobalConfiguration->getPoolPlugins();
154 std::end(mPoolPlugins), std::begin(poolPlugins), std::end(poolPlugins));
156 for (
const auto& plugin : mGlobalConfiguration->getPlugins()) {
157 mPlugins.push_back(plugin);
158 initializeCardResources(plugin);
163CardProfileManagerAdapter::initializeCardResources(
164 std::shared_ptr<Plugin> plugin)
166 for (
const auto& reader : plugin->getReaders()) {
167 std::shared_ptr<ReaderManagerAdapter> readerManager
168 = mService->getReaderManager(reader);
169 initializeCardResource(readerManager);
174CardProfileManagerAdapter::initializeCardResource(
175 std::shared_ptr<ReaderManagerAdapter> readerManager)
177 if (isReaderAccepted(readerManager->getReader())) {
178 readerManager->activate();
180 std::shared_ptr<CardResourceAdapter> cardResource
181 = readerManager->matches(
182 mCardProfile->getCardResourceProfileExtension());
189 if (cardResource !=
nullptr) {
190 if (!Arrays::contains(mCardResources, cardResource)) {
191 mCardResources.push_back(cardResource);
193 "New card resource added [profile=%, cardResource=%]\n",
194 mCardProfile->getProfileName(),
195 CardResourceServiceAdapter::getCardResourceInfo(
199 "Card resource already present [profile=%, cardResource=%]\n",
200 mCardProfile->getProfileName(),
201 CardResourceServiceAdapter::getCardResourceInfo(
209CardProfileManagerAdapter::isReaderAccepted(std::shared_ptr<CardReader> reader)
211 return mReaderNameRegexPattern ==
nullptr
212 || mReaderNameRegexPattern->matcher(reader->getName())->matches();
216CardProfileManagerAdapter::pauseIfNeeded(
217 std::shared_ptr<CardResource> cardResource)
219 if (cardResource ==
nullptr
220 && mGlobalConfiguration->isBlockingAllocationMode()) {
222 Thread::sleep(mGlobalConfiguration->getCycleDurationMillis());
223 }
catch (
const InterruptedException& e) {
224 mLogger->error(
"Unexpected sleep interruption", e);
230std::shared_ptr<CardResource>
231CardProfileManagerAdapter::getRegularOrPoolCardResource()
233 std::shared_ptr<CardResource> cardResource =
nullptr;
235 if (mGlobalConfiguration->isUsePoolFirst()) {
236 cardResource = getPoolCardResource();
237 if (cardResource ==
nullptr) {
238 cardResource = getRegularCardResource();
241 cardResource = getRegularCardResource();
242 if (cardResource ==
nullptr) {
243 cardResource = getPoolCardResource();
250std::shared_ptr<CardResource>
251CardProfileManagerAdapter::getRegularCardResource()
253 std::shared_ptr<CardResource> result =
nullptr;
254 std::vector<std::shared_ptr<CardResource>> unusableCardResources;
256 for (
const auto& cardResource : mCardResources) {
257 std::shared_ptr<CardReader> reader = cardResource->getReader();
259 std::shared_ptr<ReaderManagerAdapter> readerManager
260 = mService->getReaderManager(reader);
261 if (readerManager !=
nullptr) {
263 if (readerManager->lock(
265 mCardProfile->getCardResourceProfileExtension())) {
266 int cardResourceIndex
267 = Arrays::indexOf(mCardResources, cardResource);
268 updateCardResourcesOrder(cardResourceIndex);
269 result = cardResource;
272 }
catch (
const IllegalStateException& e) {
274 unusableCardResources.push_back(cardResource);
277 unusableCardResources.push_back(cardResource);
283 for (
const auto& cardResource : unusableCardResources) {
284 mService->removeCardResource(cardResource);
291CardProfileManagerAdapter::updateCardResourcesOrder(
const int cardResourceIndex)
293 if (mGlobalConfiguration->getAllocationStrategy()
294 == AllocationStrategy::CYCLIC) {
296 mCardResources.begin(),
297 mCardResources.begin() - cardResourceIndex - 1,
298 mCardResources.end());
301 mGlobalConfiguration->getAllocationStrategy()
302 == AllocationStrategy::RANDOM) {
303 auto rng = std::default_random_engine {};
304 std::shuffle(std::begin(mCardResources), std::end(mCardResources), rng);
308std::shared_ptr<CardResource>
309CardProfileManagerAdapter::getPoolCardResource()
311 std::shared_ptr<CardResourceProfileExtension> cardProfileExtension
312 = mCardProfile->getCardResourceProfileExtension();
314 for (
const std::shared_ptr<PoolPlugin>& poolPlugin : mPoolPlugins) {
316 std::shared_ptr<CardReader> reader = poolPlugin->allocateReader(
317 mCardProfile->getReaderGroupReference());
319 if (reader !=
nullptr) {
320 std::shared_ptr<SmartCard> selectedSmartCard
321 = poolPlugin->getSelectedSmartCard(reader);
323 std::shared_ptr<SmartCard> smartCard
324 = selectedSmartCard !=
nullptr
325 ? cardProfileExtension->matches(selectedSmartCard)
326 : cardProfileExtension->matches(
328 SmartCardServiceProvider::getService()
329 ->getReaderApiFactory());
331 if (smartCard !=
nullptr) {
332 std::shared_ptr<KeypleReaderExtension> readerExtension
333 = poolPlugin->getReaderExtension(
334 typeid(KeypleReaderExtension), reader->getName());
336 auto cardResource = std::make_shared<CardResourceAdapter>(
337 reader, readerExtension, smartCard);
339 mService->registerPoolCardResource(
340 cardResource, poolPlugin);
345 releaseReaderSilently(poolPlugin, reader);
348 }
catch (
const KeyplePluginException&) {
357CardProfileManagerAdapter::releaseReaderSilently(
358 std::shared_ptr<PoolPlugin> poolPlugin, std::shared_ptr<CardReader> reader)
361 poolPlugin->releaseReader(reader);
362 }
catch (
const Exception&) {
PluginsConfigurator::AllocationStrategy AllocationStrategy