14#include "keyple/core/service/ObservableLocalPluginAdapter.hpp"
21#include "keyple/core/plugin/PluginIOException.hpp"
22#include "keyple/core/service/KeyplePluginException.hpp"
23#include "keyple/core/service/PluginEventAdapter.hpp"
24#include "keyple/core/util/cpp/Arrays.hpp"
25#include "keyple/core/util/cpp/exception/InterruptedException.hpp"
31using keyple::core::plugin::PluginIOException;
32using keyple::core::util::cpp::Arrays;
33using keyple::core::util::cpp::exception::InterruptedException;
41ObservableLocalPluginAdapter::ObservableLocalPluginAdapter(
42 std::shared_ptr<ObservablePluginSpi> observablePluginSpi)
43: AbstractObservableLocalPluginAdapter(observablePluginSpi)
44, mObservablePluginSpi(observablePluginSpi)
48ObservableLocalPluginAdapter::~ObservableLocalPluginAdapter()
52 while (mThread->mRunning || !mThread->mTerminated) {
58ObservableLocalPluginAdapter::isMonitoring()
const
60 return mThread !=
nullptr && mThread->isAlive() && mThread->isMonitoring();
64ObservableLocalPluginAdapter::addObserver(
65 std::shared_ptr<PluginObserverSpi> observer)
67 AbstractObservableLocalPluginAdapter::addObserver(observer);
69 if (countObservers() == 1) {
70 mLogger->info(
"[plugin=%] Starting reader monitoring\n", getName());
71 mThread = std::make_shared<EventThread>(getName(),
this);
72 mThread->setName(
"PluginEventMonitoringThread");
73 mThread->setUncaughtExceptionHandler(
74 std::make_shared<UncaughtExceptionHandler>(
this));
76 while (!mThread->mStarted) {
82ObservableLocalPluginAdapter::removeObserver(
83 const std::shared_ptr<PluginObserverSpi> observer)
85 Assert::getInstance().notNull(observer,
"observer");
87 if (Arrays::contains(getObservationManager()->getObservers(), observer)) {
88 AbstractObservableLocalPluginAdapter::removeObserver(observer);
90 if (countObservers() == 0) {
91 if (mThread !=
nullptr) {
94 "[plugin=%] Reader monitoring stopped\n", getName());
101ObservableLocalPluginAdapter::clearObservers()
103 AbstractObservableLocalPluginAdapter::clearObservers();
105 if (mThread !=
nullptr) {
107 mLogger->info(
"[plugin=%] Reader monitoring stopped\n", getName());
114ObservableLocalPluginAdapter::UncaughtExceptionHandler::
115 UncaughtExceptionHandler(ObservableLocalPluginAdapter* parent)
121ObservableLocalPluginAdapter::UncaughtExceptionHandler::uncaughtException(
122 std::shared_ptr<Thread> , std::unique_ptr<Exception> e)
124 mParent->getObservationManager()
125 ->getObservationExceptionHandler()
126 ->onPluginObservationError(mParent->mThread->mPluginName, std::move(e));
133ObservableLocalPluginAdapter::EventThread::EventThread(
134 const std::string& pluginName, ObservableLocalPluginAdapter* parent)
135: Thread(std::string(
"ObservableLocalPluginAdapter-") + pluginName)
136, mPluginName(pluginName)
137, mMonitoringCycleDuration(
138 parent->mObservablePluginSpi->getMonitoringCycleDuration())
147ObservableLocalPluginAdapter::EventThread::end()
154ObservableLocalPluginAdapter::EventThread::isMonitoring()
const
160ObservableLocalPluginAdapter::EventThread::addReader(
161 const std::string& readerName)
163 std::shared_ptr<ReaderSpi> readerSpi
164 = mParent->mObservablePluginSpi->searchReader(readerName);
165 std::shared_ptr<LocalReaderAdapter> reader
166 = mParent->buildLocalReaderAdapter(readerSpi);
168 reader->doRegister();
169 mParent->getReadersMap().insert({reader->getName(), reader});
171 mParent->mLogger->info(
172 "[plugin=%] New plugged reader added to readers list [reader=%]\n",
178ObservableLocalPluginAdapter::EventThread::removeReader(
179 const std::shared_ptr<CardReader> reader)
181 std::dynamic_pointer_cast<LocalReaderAdapter>(reader)->doUnregister();
182 mParent->getReadersMap().erase(reader->getName());
184 mParent->mLogger->info(
185 "[plugin=%] Unplugged reader removed from readers list [reader=%]\n",
191ObservableLocalPluginAdapter::EventThread::notifyChanges(
193 const std::vector<std::string>& changedReaderNames)
196 mParent->mLogger->trace(
197 "Notify reader %(s): %\n",
198 type == PluginEvent::Type::READER_CONNECTED ?
"connection"
202 mParent->notifyObservers(
203 std::make_shared<PluginEventAdapter>(
204 mPluginName, changedReaderNames, type));
208ObservableLocalPluginAdapter::EventThread::processChanges(
209 const std::vector<std::string>& actualNativeReaderNames)
211 std::vector<std::string> changedReaderNames;
217 const std::vector<std::shared_ptr<CardReader>> readers
218 = mParent->getReaders();
219 for (
const auto& reader : readers) {
221 actualNativeReaderNames.begin(),
222 actualNativeReaderNames.end(),
223 reader->getName())) {
224 changedReaderNames.push_back(reader->getName());
229 if (!changedReaderNames.empty()) {
231 for (
const auto& reader : readers) {
233 actualNativeReaderNames.begin(),
234 actualNativeReaderNames.end(),
235 reader->getName())) {
236 removeReader(reader);
240 mParent->notifyObservers(
241 std::make_shared<PluginEventAdapter>(
244 PluginEvent::Type::READER_DISCONNECTED));
247 changedReaderNames.clear();
252 for (
const auto& readerName : actualNativeReaderNames) {
253 const std::vector<std::string>& readerNames = mParent->getReaderNames();
254 if (!std::count(readerNames.begin(), readerNames.end(), readerName)) {
255 addReader(readerName);
258 changedReaderNames.push_back(readerName);
263 if (!changedReaderNames.empty()) {
264 mParent->notifyObservers(
265 std::make_shared<PluginEventAdapter>(
268 PluginEvent::Type::READER_CONNECTED));
273ObservableLocalPluginAdapter::EventThread::execute()
279 bool isInError =
false;
284 const std::vector<std::string> actualNativeReaderNames
285 = mParent->mObservablePluginSpi
286 ->searchAvailableReaderNames();
290 const std::vector<std::string> currentlyRegisteredReaderNames
291 = mParent->getReaderNames();
292 if (!Arrays::containsAll(
293 currentlyRegisteredReaderNames, actualNativeReaderNames)
294 || !Arrays::containsAll(
295 actualNativeReaderNames,
296 currentlyRegisteredReaderNames)) {
297 processChanges(actualNativeReaderNames);
302 }
catch (
const PluginIOException& e) {
315 KeyplePluginException>(
new KeyplePluginException(
316 "An error occurred while monitoring the readers",
318 mParent->getObservationManager()
319 ->getObservationExceptionHandler()
320 ->onPluginObservationError(mPluginName, std::move(kpe));
325 Thread::sleep(mMonitoringCycleDuration);
327 }
catch (
const InterruptedException& e) {
329 mParent->mLogger->info(
330 "[plugin=%] Reader monitoring stopped, possibly because there is "
331 "no more registered observer",