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(
"Start monitoring the plugin [%]\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) {
93 mLogger->info(
"Plugin monitoring stopped\n");
100ObservableLocalPluginAdapter::clearObservers()
102 AbstractObservableLocalPluginAdapter::clearObservers();
104 if (mThread !=
nullptr) {
106 mLogger->info(
"Plugin monitoring stopped\n");
113ObservableLocalPluginAdapter::UncaughtExceptionHandler::
114 UncaughtExceptionHandler(ObservableLocalPluginAdapter* parent)
120ObservableLocalPluginAdapter::UncaughtExceptionHandler::uncaughtException(
121 std::shared_ptr<Thread> , std::unique_ptr<Exception> e)
123 mParent->getObservationManager()
124 ->getObservationExceptionHandler()
125 ->onPluginObservationError(mParent->mThread->mPluginName, std::move(e));
132ObservableLocalPluginAdapter::EventThread::EventThread(
133 const std::string& pluginName, ObservableLocalPluginAdapter* parent)
134: Thread(std::string(
"ObservableLocalPluginAdapter-") + pluginName)
135, mPluginName(pluginName)
136, mMonitoringCycleDuration(
137 parent->mObservablePluginSpi->getMonitoringCycleDuration())
146ObservableLocalPluginAdapter::EventThread::end()
153ObservableLocalPluginAdapter::EventThread::isMonitoring()
const
159ObservableLocalPluginAdapter::EventThread::addReader(
160 const std::string& readerName)
162 std::shared_ptr<ReaderSpi> readerSpi
163 = mParent->mObservablePluginSpi->searchReader(readerName);
164 std::shared_ptr<LocalReaderAdapter> reader
165 = mParent->buildLocalReaderAdapter(readerSpi);
167 reader->doRegister();
168 mParent->getReadersMap().insert({reader->getName(), reader});
170 mParent->mLogger->info(
171 "Plugin [%] adds plugged reader [%] to readers list\n",
177ObservableLocalPluginAdapter::EventThread::removeReader(
178 const std::shared_ptr<CardReader> reader)
180 std::dynamic_pointer_cast<LocalReaderAdapter>(reader)->doUnregister();
181 mParent->getReadersMap().erase(reader->getName());
183 mParent->mLogger->info(
184 "Plugin [%] removes unplugged reader [%] from readers list\n",
190ObservableLocalPluginAdapter::EventThread::notifyChanges(
192 const std::vector<std::string>& changedReaderNames)
195 mParent->mLogger->trace(
196 "Notify reader %(s): %\n",
197 type == PluginEvent::Type::READER_CONNECTED ?
"connection"
201 mParent->notifyObservers(
202 std::make_shared<PluginEventAdapter>(
203 mPluginName, changedReaderNames, type));
207ObservableLocalPluginAdapter::EventThread::processChanges(
208 const std::vector<std::string>& actualNativeReaderNames)
210 std::vector<std::string> changedReaderNames;
214 const std::vector<std::shared_ptr<CardReader>> readers
215 = mParent->getReaders();
216 for (
const auto& reader : readers) {
218 actualNativeReaderNames.begin(),
219 actualNativeReaderNames.end(),
220 reader->getName())) {
221 changedReaderNames.push_back(reader->getName());
226 if (!changedReaderNames.empty()) {
228 for (
const auto& reader : readers) {
230 actualNativeReaderNames.begin(),
231 actualNativeReaderNames.end(),
232 reader->getName())) {
233 removeReader(reader);
238 PluginEvent::Type::READER_DISCONNECTED, changedReaderNames);
241 changedReaderNames.clear();
246 for (
const auto& readerName : actualNativeReaderNames) {
247 const std::vector<std::string>& readerNames = mParent->getReaderNames();
248 if (!std::count(readerNames.begin(), readerNames.end(), readerName)) {
249 addReader(readerName);
252 changedReaderNames.push_back(readerName);
257 if (!changedReaderNames.empty()) {
258 notifyChanges(PluginEvent::Type::READER_CONNECTED, changedReaderNames);
263ObservableLocalPluginAdapter::EventThread::execute()
268 bool isInError =
false;
274 const std::vector<std::string> actualNativeReaderNames
275 = mParent->mObservablePluginSpi
276 ->searchAvailableReaderNames();
280 const std::vector<std::string> currentlyRegisteredReaderNames
281 = mParent->getReaderNames();
282 if (!Arrays::containsAll(
283 currentlyRegisteredReaderNames, actualNativeReaderNames)
284 || !Arrays::containsAll(
285 actualNativeReaderNames,
286 currentlyRegisteredReaderNames)) {
287 processChanges(actualNativeReaderNames);
292 }
catch (
const PluginIOException& e) {
303 auto kpe(std::unique_ptr<KeyplePluginException>(
304 new KeyplePluginException(
305 "An error occurred while monitoring the readers",
307 mParent->getObservationManager()
308 ->getObservationExceptionHandler()
309 ->onPluginObservationError(mPluginName, std::move(kpe));
314 Thread::sleep(mMonitoringCycleDuration);
316 }
catch (
const InterruptedException& e) {
318 mParent->mLogger->info(
319 "Plugin monitoring stopped, possibly because there is no more "
320 "registered observer");