From 4474cda86346f773d62b2e8b2b93db79b263f344 Mon Sep 17 00:00:00 2001 From: Jean-Pierre Fortune Date: Tue, 31 Mar 2026 16:30:40 +0200 Subject: [PATCH 1/9] docs: improve Java API documentation for ReaderSpi interface to clarify card handling behavior --- CHANGELOG.md | 36 +++++++++ .../CardRemovalWaiterAsynchronousApi.java | 2 +- .../core/plugin/TaskCanceledException.java | 9 +++ .../spi/AutonomousObservablePluginSpi.java | 4 + .../core/plugin/spi/reader/ReaderSpi.java | 74 ++++++++++++------- .../observable/ObservableReaderSpi.java | 15 +++- .../CardPresenceMonitorBlockingSpi.java | 8 +- .../removal/CardRemovalWaiterBlockingSpi.java | 2 +- .../CardRemovalWaiterNonBlockingSpi.java | 16 ++-- src/main/uml/api_class_diagram.puml | 2 + src/main/uml/api_class_diagram.svg | 2 +- 11 files changed, 128 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19fecf5..0e2a589 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,44 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- `TaskCanceledException`: added constructor `(String message, Throwable cause)` for consistency with + the other exceptions of the package. ### Changed - Migrated the CI pipeline from Jenkins to GitHub Actions. +- `ReaderSpi`: clarified class-level description to cover all reader types (not only SAM readers). +- `ReaderSpi.openPhysicalChannel()`: replaced vague "validates the opening" wording with explicit + postconditions (power-on data available, card ready for APDU commands); documented the no-op + behaviour when `checkCardPresence()` has already opened the channel; `CardIOException` now + explicitly covers the case where no card is present. +- `ReaderSpi.closePhysicalChannel()`: replaced the logical/physical distinction with two clear + rules — card present: physically close the channel; card absent: no-op. `ReaderIOException` is + now scoped to reader failures only. +- `ReaderSpi.checkCardPresence()`: documented the two behaviours based on physical channel state — + closed channel: best-effort one-shot detection; open channel: presence verification with + internal `closePhysicalChannel()` call if the card is no longer present. +- `ReaderSpi.isPhysicalChannelOpen()`: added missing `@since 2.0.0` tag. +- `ReaderSpi.getPowerOnData()`: documented that the method is meaningful only after a successful + `openPhysicalChannel()` call; clarified that an empty string may be returned when no power-on + data is available. +- `ReaderSpi.transmitApdu()`: clarified that the `61xx` handling requirement is placed at the SPI + level because its behaviour depends on the underlying transport (T=0, T=1, PC/SC). +- `CardRemovalWaiterNonBlockingSpi`: updated to document that the service calls + `checkCardPresence()` (instead of `transmitApdu()`) when polling for card removal, removing the + asymmetry with the insertion NonBlocking mode. +- `CardPresenceMonitorBlockingSpi.monitorCardPresenceDuringProcessing()`: documented that the + method returns normally when the card is removed (as opposed to raising an exception on + cancellation). +- `ObservableReaderSpi`: added documentation for the optional processing-phase interface + (`CardPresenceMonitorBlockingSpi`) and clarified that readers implementing + `CardRemovalWaiterAsynchronousSpi` do not need it. +- `AutonomousObservablePluginSpi.connect()`: clarified that the framework no longer calls this + deprecated method since version 2.2.0; implementations may provide an empty body. +### Fixed +- `CardRemovalWaiterAsynchronousApi`: corrected the class-level `@link` that was pointing to the + deprecated `WaitForCardRemovalAutonomousSpi` instead of `CardRemovalWaiterAsynchronousSpi`. +- `CardRemovalWaiterBlockingSpi.waitForCardRemoval()`: completed the truncated `@throws + ReaderIOException` description. ## [2.3.2] - 2025-04-18 ### Changed diff --git a/src/main/java/org/eclipse/keyple/core/plugin/CardRemovalWaiterAsynchronousApi.java b/src/main/java/org/eclipse/keyple/core/plugin/CardRemovalWaiterAsynchronousApi.java index 299ea43..ff1f9bb 100644 --- a/src/main/java/org/eclipse/keyple/core/plugin/CardRemovalWaiterAsynchronousApi.java +++ b/src/main/java/org/eclipse/keyple/core/plugin/CardRemovalWaiterAsynchronousApi.java @@ -13,7 +13,7 @@ /** * API associated to a {@link - * org.eclipse.keyple.core.plugin.spi.reader.observable.state.removal.WaitForCardRemovalAutonomousSpi} + * org.eclipse.keyple.core.plugin.spi.reader.observable.state.removal.CardRemovalWaiterAsynchronousSpi} * * @since 2.2.0 */ diff --git a/src/main/java/org/eclipse/keyple/core/plugin/TaskCanceledException.java b/src/main/java/org/eclipse/keyple/core/plugin/TaskCanceledException.java index c18c315..151d21a 100644 --- a/src/main/java/org/eclipse/keyple/core/plugin/TaskCanceledException.java +++ b/src/main/java/org/eclipse/keyple/core/plugin/TaskCanceledException.java @@ -26,4 +26,13 @@ public class TaskCanceledException extends Exception { public TaskCanceledException(String message) { super(message); } + + /** + * @param message the message to identify the exception context + * @param cause the cause + * @since 2.3.3 + */ + public TaskCanceledException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/main/java/org/eclipse/keyple/core/plugin/spi/AutonomousObservablePluginSpi.java b/src/main/java/org/eclipse/keyple/core/plugin/spi/AutonomousObservablePluginSpi.java index f47516b..6d4ba08 100644 --- a/src/main/java/org/eclipse/keyple/core/plugin/spi/AutonomousObservablePluginSpi.java +++ b/src/main/java/org/eclipse/keyple/core/plugin/spi/AutonomousObservablePluginSpi.java @@ -26,6 +26,10 @@ public interface AutonomousObservablePluginSpi extends PluginSpi { /** * Connects the associated Keyple Core {@link AutonomousObservablePluginApi} API. * + *

This method is no longer called by the framework since version 2.2.0. Implementations + * migrating to {@link #setCallback(AutonomousObservablePluginApi)} may provide an empty body for + * this method. + * * @param autonomousObservablePluginApi The API to connect. * @since 2.0.0 * @deprecated Use {@link #setCallback(AutonomousObservablePluginApi)} instead. diff --git a/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/ReaderSpi.java b/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/ReaderSpi.java index 321fb82..290a80a 100644 --- a/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/ReaderSpi.java +++ b/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/ReaderSpi.java @@ -15,8 +15,10 @@ import org.eclipse.keyple.core.plugin.ReaderIOException; /** - * Reader able to communicate with smart cards whose purpose is to remain present in the reader (for - * example a SAM reader). + * Reader able to communicate with smart cards. + * + *

This is the base interface for all reader types, including readers with permanently present + * cards (e.g. SAM readers) and observable readers detecting card insertion and removal. * *

The target devices must comply with the following Calypsonet Terminal requirements: * @@ -40,27 +42,36 @@ public interface ReaderSpi { String getName(); /** - * Validates the opening of the physical channel. Performs the actual opening if this has not been - * done by the {@link #checkCardPresence()} method. In all cases, memorizes the new state for the - * operation of the {@link #isPhysicalChannelOpen()} method. After executing this method, the - * reader is able to send APDUs to the card. + * Ensures that the physical channel is open and that the card is ready to receive APDU commands. + * + *

On successful return: + * + *

+ * + *

If {@link #checkCardPresence()} has already opened the physical channel (e.g. for + * contactless readers performing anti-collision during presence detection), this method is a + * no-op. * * @throws ReaderIOException If the communication with the reader has failed. - * @throws CardIOException If the communication with the card has failed. + * @throws CardIOException If no card is present or if the communication with the card has failed. * @since 2.0.0 */ void openPhysicalChannel() throws ReaderIOException, CardIOException; /** - * Tells the reader that card processing is complete and that the next step is to remove the card - * from the reader. + * Closes the physical channel. * - *

If the reader has the ability to sense the presence of the card without communicating with - * it, then this method must proceed to the actual closing of the physical channel (e.g. power - * down in the case of a contact reader). Otherwise, this method is limited to changing the - * logical opening state of the physical channel and letting the removal procedure do the closing. + *

* - * @throws ReaderIOException If the communication with the reader has failed. + * @throws ReaderIOException If the card is present and the close operation fails (reader + * problem). * @since 2.0.0 */ void closePhysicalChannel() throws ReaderIOException; @@ -69,20 +80,26 @@ public interface ReaderSpi { * Tells if the physical channel is open or not. * * @return True is the physical channel is open, false if not. + * @since 2.0.0 */ boolean isPhysicalChannelOpen(); /** * Verifies the presence of a card. * - *

Depending on the reader's capabilities, this method will either use a card presence - * indicator without necessarily communicating with the card (for example, in the case of a - * contact reader equipped with a physical insertion detector using a switch), or will communicate - * with the card (in the case of contactless hunting). In the latter case, we can consider that - * the physical channel has been opened (and therefore no longer needs to be opened in the {@link - * #openPhysicalChannel()} method). + *

The behavior of this method depends on the state of the physical channel: + * + *

* - * @return True if a card is present + * @return {@code true} if a card is present, {@code false} otherwise. * @throws ReaderIOException If the communication with the reader has failed. * @since 2.0.0 */ @@ -92,6 +109,7 @@ public interface ReaderSpi { * Gets the power-on data. * *

The power-on data is defined as the data retrieved by the reader when the card is inserted. + * This method is only meaningful after {@link #openPhysicalChannel()} has returned successfully. * *

In the case of a contact reader, this is the Answer To Reset data (ATR) defined by ISO7816. * @@ -101,9 +119,11 @@ public interface ReaderSpi { * the ISO14443 protocol (ATQA, ATQB, ATS, SAK, etc). * *

These data being variable from one reader to another, they are defined here in string format - * which can be either a hexadecimal string or any other relevant information. + * which can be either a hexadecimal string or any other relevant information. An empty string may + * be returned if no power-on data is available (e.g. for a reader with a permanently powered + * card). * - * @return A not empty String. + * @return A non-null String, possibly empty. * @since 2.0.0 */ String getPowerOnData(); @@ -111,9 +131,11 @@ public interface ReaderSpi { /** * Transmits an APDU and returns its response. * - *

Caution: the implementation must handle the case where the card response is 61xy and - * execute the appropriate get response command (Calypsonet Terminal requirement - * "RL-SW-61XX.1"). + *

Caution: the implementation must handle the ISO 7816-3 T=0 protocol specificity at the + * transport level: status word {@code 61xx} (response bytes available) requires automatically + * issuing a {@code GET RESPONSE} command (Calypsonet Terminal requirement "RL-SW-61XX.1"). This + * is handled at the SPI level because its behavior depends on the underlying reader + * implementation (T=0, T=1, PC/SC). * * @param apduIn The data to be sent to the card. * @return A buffer of at least 2 bytes. diff --git a/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/observable/ObservableReaderSpi.java b/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/observable/ObservableReaderSpi.java index 2f9d5ce..3620560 100644 --- a/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/observable/ObservableReaderSpi.java +++ b/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/observable/ObservableReaderSpi.java @@ -13,13 +13,14 @@ import org.eclipse.keyple.core.plugin.spi.reader.ReaderSpi; import org.eclipse.keyple.core.plugin.spi.reader.observable.state.insertion.*; +import org.eclipse.keyple.core.plugin.spi.reader.observable.state.processing.*; import org.eclipse.keyple.core.plugin.spi.reader.observable.state.removal.*; /** * Reader able to detect the insertion and removal of cards. * *

In addition, an observable reader must also define its observation capabilities for the card - * insertion and removal steps. + * insertion, removal, and optionally processing steps. * *

For the card insertion state, it must implement one of the following interfaces: * @@ -37,6 +38,18 @@ *

  • {@link CardRemovalWaiterNonBlockingSpi} * * + *

    For the card processing state (monitoring card presence between APDU commands), it may + * optionally implement: + * + *

    + * + *

    Readers implementing {@link CardRemovalWaiterAsynchronousSpi} (e.g. Android NFC readers) do + * not need to implement {@link CardPresenceMonitorBlockingSpi}: the asynchronous removal callback + * covers all phases, including processing. + * * @since 2.0.0 */ public interface ObservableReaderSpi extends ReaderSpi { diff --git a/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/observable/state/processing/CardPresenceMonitorBlockingSpi.java b/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/observable/state/processing/CardPresenceMonitorBlockingSpi.java index a6151d0..fdff8b3 100644 --- a/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/observable/state/processing/CardPresenceMonitorBlockingSpi.java +++ b/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/observable/state/processing/CardPresenceMonitorBlockingSpi.java @@ -24,12 +24,12 @@ public interface CardPresenceMonitorBlockingSpi { /** - * Monitors the card presence indefinitely (the method is blocking as long as the card is - * present). + * Monitors the card presence indefinitely (the method is blocking as long as the card is present) + * and returns normally when the card is removed. * *

    This monitoring can be cancelled for an internal (for example timeout) or external reason - * (for example invocation of {@link #stopCardPresenceMonitoringDuringProcessing()}), in this case - * an exception is raised. + * (for example invocation of {@link #stopCardPresenceMonitoringDuringProcessing()}), in which + * case an exception is raised. * * @throws ReaderIOException If the communication with the reader has failed. * @throws TaskCanceledException If the task has been canceled and is no longer active. diff --git a/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/observable/state/removal/CardRemovalWaiterBlockingSpi.java b/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/observable/state/removal/CardRemovalWaiterBlockingSpi.java index e1b3803..1982520 100644 --- a/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/observable/state/removal/CardRemovalWaiterBlockingSpi.java +++ b/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/observable/state/removal/CardRemovalWaiterBlockingSpi.java @@ -32,7 +32,7 @@ public interface CardRemovalWaiterBlockingSpi { *

    This wait can be cancelled for an internal (for example timeout) or external reason (for * example invocation of {@link #stopWaitForCardRemoval()}), in this case an exception is raised. * - * @throws ReaderIOException If the communication with the reader + * @throws ReaderIOException If the communication with the reader has failed. * @throws TaskCanceledException If the task has been canceled and is no longer active * @since 2.2.0 */ diff --git a/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/observable/state/removal/CardRemovalWaiterNonBlockingSpi.java b/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/observable/state/removal/CardRemovalWaiterNonBlockingSpi.java index baaeddd..d568511 100644 --- a/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/observable/state/removal/CardRemovalWaiterNonBlockingSpi.java +++ b/src/main/java/org/eclipse/keyple/core/plugin/spi/reader/observable/state/removal/CardRemovalWaiterNonBlockingSpi.java @@ -12,20 +12,20 @@ package org.eclipse.keyple.core.plugin.spi.reader.observable.state.removal; /** - * This SPI is specifically designed for plugins that don't handle card removal autonomously but - * requires the sending of an APDU to detect the card removal. + * This SPI is specifically designed for plugins that don't handle card removal autonomously. * *

    When a plugin implements this SPI, the {@link - * org.eclipse.keyple.core.plugin.spi.reader.ReaderSpi#transmitApdu(byte[])} method will be called + * org.eclipse.keyple.core.plugin.spi.reader.ReaderSpi#checkCardPresence()} method will be called * periodically by the service when a card removal is expected. The card is considered removed when - * the transmission fails. + * {@code checkCardPresence()} returns {@code false} (which also triggers the internal closure of + * the physical channel). * - *

    The value returned by the {@link #getCardRemovalMonitoringSleepDuration()} will be used as an + *

    The value returned by {@link #getCardRemovalMonitoringSleepDuration()} will be used as an * argument to {@link Thread#sleep(long)} between two calls to {@link - * org.eclipse.keyple.core.plugin.spi.reader.ReaderSpi#transmitApdu}. + * org.eclipse.keyple.core.plugin.spi.reader.ReaderSpi#checkCardPresence()}. * *

    A typical example of readers conforming to this mode of operation are terminals embedding a - * slave RF communication module without card presence feature. + * slave RF communication module without autonomous card presence detection. * * @since 2.2.0 */ @@ -33,7 +33,7 @@ public interface CardRemovalWaiterNonBlockingSpi { /** * Provides the value of the sleep duration (in milliseconds) inserted between two calls to {@link - * org.eclipse.keyple.core.plugin.spi.reader.ReaderSpi#transmitApdu}. + * org.eclipse.keyple.core.plugin.spi.reader.ReaderSpi#checkCardPresence()}. * * @return A positive value (0 is allowed). * @since 2.2.0 diff --git a/src/main/uml/api_class_diagram.puml b/src/main/uml/api_class_diagram.puml index 7bc2abf..3f9254d 100644 --- a/src/main/uml/api_class_diagram.puml +++ b/src/main/uml/api_class_diagram.puml @@ -88,6 +88,8 @@ package "org.eclipse.keyple.core.plugin" as api { } +class "<>\n**final** TaskCanceledException" as TaskCanceledException <> { +TaskCanceledException (String message) + +TaskCanceledException (String message, + \tThrowable cause) } package spi { together { diff --git a/src/main/uml/api_class_diagram.svg b/src/main/uml/api_class_diagram.svg index 368e623..81fbe53 100644 --- a/src/main/uml/api_class_diagram.svg +++ b/src/main/uml/api_class_diagram.svg @@ -1 +1 @@ -Keyple - keyple-plugin-java-api - 2.3.+ (2024-03-26)Keyple - keyple-plugin-java-api - 2.3.+ (2024-03-26)org.eclipse.keyple.core.pluginspireaderobservablestateprocessinginsertionremovalfinalPluginApiPropertiesfinalString VERSIONAutonomousObservablePluginApivoid onReaderConnected (Set<ReaderSpi> readers)void onReaderDisconnected (Set<String> readerNames)WaitForCardInsertionAutonomousReaderApivoid onCardInserted ()WaitForCardRemovalAutonomousReaderApivoid onCardRemoved ()CardInsertionWaiterAsynchronousApivoid onCardInserted ()CardRemovalWaiterAsynchronousApivoid onCardRemoved ()«Exception»finalPluginIOExceptionPluginIOException (String message)PluginIOException (String message,Throwable cause)«Exception»finalReaderIOExceptionReaderIOException (String message)ReaderIOException (String message,Throwable cause)«Exception»finalCardIOExceptionCardIOException (String message)CardIOException (String message,Throwable cause)«Exception»finalTaskCanceledExceptionTaskCanceledException (String message)PoolPluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPoolPluginName ()PoolPluginSpi getPoolPlugin ()PluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPluginName ()PluginSpi getPlugin ()PoolPluginSpiString getName ()SortedSet<String> getReaderGroupReferences ()PoolReaderSpi allocateReader (String readerGroupReference)void releaseReader (ReaderSpi readerSpi)void onUnregister ()PluginSpiString getName ()Set<ReaderSpi> searchAvailableReaders ()void onUnregister ()ObservablePluginSpiint getMonitoringCycleDuration ()Set<String> searchAvailableReaderNames ()ReaderSpi searchReader (String readerName)AutonomousObservablePluginSpivoid connect (AutonomousObservablePluginApiautonomousObservablePluginApi)void setCallback (AutonomousObservablePluginApi callback)ReaderSpiString getName () void openPhysicalChannel ()void closePhysicalChannel ()boolean isPhysicalChannelOpen () boolean checkCardPresence ()String getPowerOnData ()byte[] transmitApdu (byte[] apduIn)boolean isContactless ()void onUnregister ()PoolReaderSpiObject getSelectedSmartCard ()ConfigurableReaderSpiboolean isProtocolSupported (String readerProtocol)void activateProtocol (String readerProtocol)void deactivateProtocol (String readerProtocol)boolean isCurrentProtocol (String readerProtocol)AutonomousSelectionReaderSpibyte[] openChannelForAid (byte[] dfName, byte isoControlMask)void closeLogicalChannel ()ObservableReaderSpivoid onStartDetection ()void onStopDetection ()WaitForCardRemovalBlockingDuringProcessingSpivoid waitForCardRemovalDuringProcessing ()void stopWaitForCardRemovalDuringProcessing ()DontWaitForCardRemovalDuringProcessingSpiCardPresenceMonitorBlockingSpivoid monitorCardPresenceDuringProcessing ()void stopCardPresenceMonitoringDuringProcessing ()WaitForCardInsertionBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()CardInsertionWaiterBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()WaitForCardInsertionNonBlockingSpiCardInsertionWaiterNonBlockingSpiint getCardInsertionMonitoringSleepDuration ()WaitForCardInsertionAutonomousSpivoid connect (WaitForCardInsertionAutonomousReaderApiwaitForCardInsertionAutonomousReaderApi)CardInsertionWaiterAsynchronousSpivoid setCallback (CardInsertionWaiterAsynchronousApi callback)WaitForCardRemovalBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()CardRemovalWaiterBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()WaitForCardRemovalNonBlockingSpiCardRemovalWaiterNonBlockingSpiint getCardRemovalMonitoringSleepDuration ()WaitForCardRemovalAutonomousSpivoid connect (WaitForCardRemovalAutonomousReaderApiwaitForCardRemovalAutonomousReaderApi)CardRemovalWaiterAsynchronousSpivoid setCallback (CardRemovalWaiterAsynchronousApi callback)provideAPI versionprovideprovideprovideAPI versionprovideprovideuseuseuseuseuse \ No newline at end of file +Keyple - keyple-plugin-java-api - 2.3.+ (2024-03-26)Keyple - keyple-plugin-java-api - 2.3.+ (2024-03-26)org.eclipse.keyple.core.pluginspireaderobservablestateprocessinginsertionremovalfinalPluginApiPropertiesfinalString VERSIONAutonomousObservablePluginApivoid onReaderConnected (Set<ReaderSpi> readers)void onReaderDisconnected (Set<String> readerNames)WaitForCardInsertionAutonomousReaderApivoid onCardInserted ()WaitForCardRemovalAutonomousReaderApivoid onCardRemoved ()CardInsertionWaiterAsynchronousApivoid onCardInserted ()CardRemovalWaiterAsynchronousApivoid onCardRemoved ()«Exception»finalPluginIOExceptionPluginIOException (String message)PluginIOException (String message,Throwable cause)«Exception»finalReaderIOExceptionReaderIOException (String message)ReaderIOException (String message,Throwable cause)«Exception»finalCardIOExceptionCardIOException (String message)CardIOException (String message,Throwable cause)«Exception»finalTaskCanceledExceptionTaskCanceledException (String message)TaskCanceledException (String message,Throwable cause)PoolPluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPoolPluginName ()PoolPluginSpi getPoolPlugin ()PluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPluginName ()PluginSpi getPlugin ()PoolPluginSpiString getName ()SortedSet<String> getReaderGroupReferences ()PoolReaderSpi allocateReader (String readerGroupReference)void releaseReader (ReaderSpi readerSpi)void onUnregister ()PluginSpiString getName ()Set<ReaderSpi> searchAvailableReaders ()void onUnregister ()ObservablePluginSpiint getMonitoringCycleDuration ()Set<String> searchAvailableReaderNames ()ReaderSpi searchReader (String readerName)AutonomousObservablePluginSpivoid connect (AutonomousObservablePluginApiautonomousObservablePluginApi)void setCallback (AutonomousObservablePluginApi callback)ReaderSpiString getName () void openPhysicalChannel ()void closePhysicalChannel ()boolean isPhysicalChannelOpen () boolean checkCardPresence ()String getPowerOnData ()byte[] transmitApdu (byte[] apduIn)boolean isContactless ()void onUnregister ()PoolReaderSpiObject getSelectedSmartCard ()ConfigurableReaderSpiboolean isProtocolSupported (String readerProtocol)void activateProtocol (String readerProtocol)void deactivateProtocol (String readerProtocol)boolean isCurrentProtocol (String readerProtocol)AutonomousSelectionReaderSpibyte[] openChannelForAid (byte[] dfName, byte isoControlMask)void closeLogicalChannel ()ObservableReaderSpivoid onStartDetection ()void onStopDetection ()WaitForCardRemovalBlockingDuringProcessingSpivoid waitForCardRemovalDuringProcessing ()void stopWaitForCardRemovalDuringProcessing ()DontWaitForCardRemovalDuringProcessingSpiCardPresenceMonitorBlockingSpivoid monitorCardPresenceDuringProcessing ()void stopCardPresenceMonitoringDuringProcessing ()WaitForCardInsertionBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()CardInsertionWaiterBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()WaitForCardInsertionNonBlockingSpiCardInsertionWaiterNonBlockingSpiint getCardInsertionMonitoringSleepDuration ()WaitForCardInsertionAutonomousSpivoid connect (WaitForCardInsertionAutonomousReaderApiwaitForCardInsertionAutonomousReaderApi)CardInsertionWaiterAsynchronousSpivoid setCallback (CardInsertionWaiterAsynchronousApi callback)WaitForCardRemovalBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()CardRemovalWaiterBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()WaitForCardRemovalNonBlockingSpiCardRemovalWaiterNonBlockingSpiint getCardRemovalMonitoringSleepDuration ()WaitForCardRemovalAutonomousSpivoid connect (WaitForCardRemovalAutonomousReaderApiwaitForCardRemovalAutonomousReaderApi)CardRemovalWaiterAsynchronousSpivoid setCallback (CardRemovalWaiterAsynchronousApi callback)provideAPI versionprovideprovideprovideAPI versionprovideprovideuseuseuseuseuse \ No newline at end of file From 11d6396db27ce366c8d9bae242bff38c07dae6f1 Mon Sep 17 00:00:00 2001 From: Jean-Pierre Fortune Date: Tue, 31 Mar 2026 17:01:42 +0200 Subject: [PATCH 2/9] fix: correct UML diagram to display updated TaskCanceledException constructor formatting --- src/main/uml/api_class_diagram.puml | 4 ++-- src/main/uml/api_class_diagram.svg | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/uml/api_class_diagram.puml b/src/main/uml/api_class_diagram.puml index 3f9254d..9ed75b7 100644 --- a/src/main/uml/api_class_diagram.puml +++ b/src/main/uml/api_class_diagram.puml @@ -88,8 +88,8 @@ package "org.eclipse.keyple.core.plugin" as api { } +class "<>\n**final** TaskCanceledException" as TaskCanceledException <> { +TaskCanceledException (String message) - +TaskCanceledException (String message, - \tThrowable cause) + +TaskCanceledException (String message, + \tThrowable cause) } package spi { together { diff --git a/src/main/uml/api_class_diagram.svg b/src/main/uml/api_class_diagram.svg index 81fbe53..2e8b29a 100644 --- a/src/main/uml/api_class_diagram.svg +++ b/src/main/uml/api_class_diagram.svg @@ -1 +1 @@ -Keyple - keyple-plugin-java-api - 2.3.+ (2024-03-26)Keyple - keyple-plugin-java-api - 2.3.+ (2024-03-26)org.eclipse.keyple.core.pluginspireaderobservablestateprocessinginsertionremovalfinalPluginApiPropertiesfinalString VERSIONAutonomousObservablePluginApivoid onReaderConnected (Set<ReaderSpi> readers)void onReaderDisconnected (Set<String> readerNames)WaitForCardInsertionAutonomousReaderApivoid onCardInserted ()WaitForCardRemovalAutonomousReaderApivoid onCardRemoved ()CardInsertionWaiterAsynchronousApivoid onCardInserted ()CardRemovalWaiterAsynchronousApivoid onCardRemoved ()«Exception»finalPluginIOExceptionPluginIOException (String message)PluginIOException (String message,Throwable cause)«Exception»finalReaderIOExceptionReaderIOException (String message)ReaderIOException (String message,Throwable cause)«Exception»finalCardIOExceptionCardIOException (String message)CardIOException (String message,Throwable cause)«Exception»finalTaskCanceledExceptionTaskCanceledException (String message)TaskCanceledException (String message,Throwable cause)PoolPluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPoolPluginName ()PoolPluginSpi getPoolPlugin ()PluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPluginName ()PluginSpi getPlugin ()PoolPluginSpiString getName ()SortedSet<String> getReaderGroupReferences ()PoolReaderSpi allocateReader (String readerGroupReference)void releaseReader (ReaderSpi readerSpi)void onUnregister ()PluginSpiString getName ()Set<ReaderSpi> searchAvailableReaders ()void onUnregister ()ObservablePluginSpiint getMonitoringCycleDuration ()Set<String> searchAvailableReaderNames ()ReaderSpi searchReader (String readerName)AutonomousObservablePluginSpivoid connect (AutonomousObservablePluginApiautonomousObservablePluginApi)void setCallback (AutonomousObservablePluginApi callback)ReaderSpiString getName () void openPhysicalChannel ()void closePhysicalChannel ()boolean isPhysicalChannelOpen () boolean checkCardPresence ()String getPowerOnData ()byte[] transmitApdu (byte[] apduIn)boolean isContactless ()void onUnregister ()PoolReaderSpiObject getSelectedSmartCard ()ConfigurableReaderSpiboolean isProtocolSupported (String readerProtocol)void activateProtocol (String readerProtocol)void deactivateProtocol (String readerProtocol)boolean isCurrentProtocol (String readerProtocol)AutonomousSelectionReaderSpibyte[] openChannelForAid (byte[] dfName, byte isoControlMask)void closeLogicalChannel ()ObservableReaderSpivoid onStartDetection ()void onStopDetection ()WaitForCardRemovalBlockingDuringProcessingSpivoid waitForCardRemovalDuringProcessing ()void stopWaitForCardRemovalDuringProcessing ()DontWaitForCardRemovalDuringProcessingSpiCardPresenceMonitorBlockingSpivoid monitorCardPresenceDuringProcessing ()void stopCardPresenceMonitoringDuringProcessing ()WaitForCardInsertionBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()CardInsertionWaiterBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()WaitForCardInsertionNonBlockingSpiCardInsertionWaiterNonBlockingSpiint getCardInsertionMonitoringSleepDuration ()WaitForCardInsertionAutonomousSpivoid connect (WaitForCardInsertionAutonomousReaderApiwaitForCardInsertionAutonomousReaderApi)CardInsertionWaiterAsynchronousSpivoid setCallback (CardInsertionWaiterAsynchronousApi callback)WaitForCardRemovalBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()CardRemovalWaiterBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()WaitForCardRemovalNonBlockingSpiCardRemovalWaiterNonBlockingSpiint getCardRemovalMonitoringSleepDuration ()WaitForCardRemovalAutonomousSpivoid connect (WaitForCardRemovalAutonomousReaderApiwaitForCardRemovalAutonomousReaderApi)CardRemovalWaiterAsynchronousSpivoid setCallback (CardRemovalWaiterAsynchronousApi callback)provideAPI versionprovideprovideprovideAPI versionprovideprovideuseuseuseuseuse \ No newline at end of file +Keyple - keyple-plugin-java-api - 2.3.+ (2024-03-26)Keyple - keyple-plugin-java-api - 2.3.+ (2024-03-26)org.eclipse.keyple.core.pluginspireaderobservablestateprocessinginsertionremovalfinalPluginApiPropertiesfinalString VERSIONAutonomousObservablePluginApivoid onReaderConnected (Set<ReaderSpi> readers)void onReaderDisconnected (Set<String> readerNames)WaitForCardInsertionAutonomousReaderApivoid onCardInserted ()WaitForCardRemovalAutonomousReaderApivoid onCardRemoved ()CardInsertionWaiterAsynchronousApivoid onCardInserted ()CardRemovalWaiterAsynchronousApivoid onCardRemoved ()«Exception»finalPluginIOExceptionPluginIOException (String message)PluginIOException (String message,Throwable cause)«Exception»finalReaderIOExceptionReaderIOException (String message)ReaderIOException (String message,Throwable cause)«Exception»finalCardIOExceptionCardIOException (String message)CardIOException (String message,Throwable cause)«Exception»finalTaskCanceledExceptionTaskCanceledException (String message)TaskCanceledException (String message,   Throwable cause)PoolPluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPoolPluginName ()PoolPluginSpi getPoolPlugin ()PluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPluginName ()PluginSpi getPlugin ()PoolPluginSpiString getName ()SortedSet<String> getReaderGroupReferences ()PoolReaderSpi allocateReader (String readerGroupReference)void releaseReader (ReaderSpi readerSpi)void onUnregister ()PluginSpiString getName ()Set<ReaderSpi> searchAvailableReaders ()void onUnregister ()ObservablePluginSpiint getMonitoringCycleDuration ()Set<String> searchAvailableReaderNames ()ReaderSpi searchReader (String readerName)AutonomousObservablePluginSpivoid connect (AutonomousObservablePluginApiautonomousObservablePluginApi)void setCallback (AutonomousObservablePluginApi callback)ReaderSpiString getName () void openPhysicalChannel ()void closePhysicalChannel ()boolean isPhysicalChannelOpen () boolean checkCardPresence ()String getPowerOnData ()byte[] transmitApdu (byte[] apduIn)boolean isContactless ()void onUnregister ()PoolReaderSpiObject getSelectedSmartCard ()ConfigurableReaderSpiboolean isProtocolSupported (String readerProtocol)void activateProtocol (String readerProtocol)void deactivateProtocol (String readerProtocol)boolean isCurrentProtocol (String readerProtocol)AutonomousSelectionReaderSpibyte[] openChannelForAid (byte[] dfName, byte isoControlMask)void closeLogicalChannel ()ObservableReaderSpivoid onStartDetection ()void onStopDetection ()WaitForCardRemovalBlockingDuringProcessingSpivoid waitForCardRemovalDuringProcessing ()void stopWaitForCardRemovalDuringProcessing ()DontWaitForCardRemovalDuringProcessingSpiCardPresenceMonitorBlockingSpivoid monitorCardPresenceDuringProcessing ()void stopCardPresenceMonitoringDuringProcessing ()WaitForCardInsertionBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()CardInsertionWaiterBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()WaitForCardInsertionNonBlockingSpiCardInsertionWaiterNonBlockingSpiint getCardInsertionMonitoringSleepDuration ()WaitForCardInsertionAutonomousSpivoid connect (WaitForCardInsertionAutonomousReaderApiwaitForCardInsertionAutonomousReaderApi)CardInsertionWaiterAsynchronousSpivoid setCallback (CardInsertionWaiterAsynchronousApi callback)WaitForCardRemovalBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()CardRemovalWaiterBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()WaitForCardRemovalNonBlockingSpiCardRemovalWaiterNonBlockingSpiint getCardRemovalMonitoringSleepDuration ()WaitForCardRemovalAutonomousSpivoid connect (WaitForCardRemovalAutonomousReaderApiwaitForCardRemovalAutonomousReaderApi)CardRemovalWaiterAsynchronousSpivoid setCallback (CardRemovalWaiterAsynchronousApi callback)provideAPI versionprovideprovideprovideAPI versionprovideprovideuseuseuseuseuse \ No newline at end of file From 1d83ba477b347d250452841a07fefe603dd9836f Mon Sep 17 00:00:00 2001 From: Jean-Pierre Fortune Date: Tue, 31 Mar 2026 17:02:06 +0200 Subject: [PATCH 3/9] fix: update UML diagram title to reflect new release date --- src/main/uml/api_class_diagram.puml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/uml/api_class_diagram.puml b/src/main/uml/api_class_diagram.puml index 9ed75b7..70c6e82 100644 --- a/src/main/uml/api_class_diagram.puml +++ b/src/main/uml/api_class_diagram.puml @@ -1,6 +1,6 @@ @startuml title - Keyple - keyple-plugin-java-api - 2.3.+ (2024-03-26) + Keyple - keyple-plugin-java-api - 2.3.+ (2026-03-31) end title ' == THEME == From 7904df3c17a0f6f752cc5a17e8db6cd558877667 Mon Sep 17 00:00:00 2001 From: Jean-Pierre Fortune Date: Tue, 31 Mar 2026 17:10:45 +0200 Subject: [PATCH 4/9] docs: update CHANGELOG with clarified ReaderSpi contracts and other Javadoc improvements --- CHANGELOG.md | 44 ++++++++++---------------------------------- 1 file changed, 10 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e2a589..907cfcd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,43 +6,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added -- `TaskCanceledException`: added constructor `(String message, Throwable cause)` for consistency with - the other exceptions of the package. +- `TaskCanceledException`: added constructor `(String message, Throwable cause)` for consistency + with the other exceptions of the package. ### Changed - Migrated the CI pipeline from Jenkins to GitHub Actions. -- `ReaderSpi`: clarified class-level description to cover all reader types (not only SAM readers). -- `ReaderSpi.openPhysicalChannel()`: replaced vague "validates the opening" wording with explicit - postconditions (power-on data available, card ready for APDU commands); documented the no-op - behaviour when `checkCardPresence()` has already opened the channel; `CardIOException` now - explicitly covers the case where no card is present. -- `ReaderSpi.closePhysicalChannel()`: replaced the logical/physical distinction with two clear - rules — card present: physically close the channel; card absent: no-op. `ReaderIOException` is - now scoped to reader failures only. -- `ReaderSpi.checkCardPresence()`: documented the two behaviours based on physical channel state — - closed channel: best-effort one-shot detection; open channel: presence verification with - internal `closePhysicalChannel()` call if the card is no longer present. -- `ReaderSpi.isPhysicalChannelOpen()`: added missing `@since 2.0.0` tag. -- `ReaderSpi.getPowerOnData()`: documented that the method is meaningful only after a successful - `openPhysicalChannel()` call; clarified that an empty string may be returned when no power-on - data is available. -- `ReaderSpi.transmitApdu()`: clarified that the `61xx` handling requirement is placed at the SPI - level because its behaviour depends on the underlying transport (T=0, T=1, PC/SC). -- `CardRemovalWaiterNonBlockingSpi`: updated to document that the service calls - `checkCardPresence()` (instead of `transmitApdu()`) when polling for card removal, removing the - asymmetry with the insertion NonBlocking mode. -- `CardPresenceMonitorBlockingSpi.monitorCardPresenceDuringProcessing()`: documented that the - method returns normally when the card is removed (as opposed to raising an exception on - cancellation). -- `ObservableReaderSpi`: added documentation for the optional processing-phase interface - (`CardPresenceMonitorBlockingSpi`) and clarified that readers implementing - `CardRemovalWaiterAsynchronousSpi` do not need it. -- `AutonomousObservablePluginSpi.connect()`: clarified that the framework no longer calls this - deprecated method since version 2.2.0; implementations may provide an empty body. +- `ReaderSpi`: clarified the contracts of `openPhysicalChannel()`, `closePhysicalChannel()` and + `checkCardPresence()` regarding physical channel state management (see Javadoc for details). +- `ReaderSpi.getPowerOnData()`: documented lifecycle (meaningful only after a successful + `openPhysicalChannel()`) and allowed empty return value. +- `CardRemovalWaiterNonBlockingSpi`: the service now uses `checkCardPresence()` instead of + `transmitApdu()` for card removal polling. +- Various Javadoc corrections and minor clarifications. ### Fixed -- `CardRemovalWaiterAsynchronousApi`: corrected the class-level `@link` that was pointing to the - deprecated `WaitForCardRemovalAutonomousSpi` instead of `CardRemovalWaiterAsynchronousSpi`. -- `CardRemovalWaiterBlockingSpi.waitForCardRemoval()`: completed the truncated `@throws - ReaderIOException` description. +- `CardRemovalWaiterAsynchronousApi`: corrected `@link` pointing to a deprecated SPI. ## [2.3.2] - 2025-04-18 ### Changed From cd52ddbfc5346572312e1b5d2d3f0a750d0748b8 Mon Sep 17 00:00:00 2001 From: Jean-Pierre Fortune Date: Tue, 31 Mar 2026 17:15:49 +0200 Subject: [PATCH 5/9] fix: update UML diagram to reflect version 2.4 changes, remove outdated formatting --- src/main/uml/api_class_diagram.puml | 8 ++++---- src/main/uml/api_class_diagram.svg | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/uml/api_class_diagram.puml b/src/main/uml/api_class_diagram.puml index 70c6e82..0304cea 100644 --- a/src/main/uml/api_class_diagram.puml +++ b/src/main/uml/api_class_diagram.puml @@ -1,6 +1,6 @@ @startuml title - Keyple - keyple-plugin-java-api - 2.3.+ (2026-03-31) + Keyple - keyple-plugin-java-api - 2.4.+ (2026-03-31) end title ' == THEME == @@ -171,9 +171,9 @@ package "org.eclipse.keyple.core.plugin" as api { } +interface "DontWaitForCardRemovalDuringProcessingSpi" as DontWaitForCardRemovalDuringProcessingSpi <> { } - +interface "CardPresenceMonitorBlockingSpi" as CardPresenceMonitorBlockingSpi <> { - +void monitorCardPresenceDuringProcessing () - +void stopCardPresenceMonitoringDuringProcessing () + +interface "CardPresenceMonitorBlockingSpi" as CardPresenceMonitorBlockingSpi <> { + +void monitorCardPresenceDuringProcessing () + +void stopCardPresenceMonitoringDuringProcessing () } } package insertion { diff --git a/src/main/uml/api_class_diagram.svg b/src/main/uml/api_class_diagram.svg index 2e8b29a..a627d41 100644 --- a/src/main/uml/api_class_diagram.svg +++ b/src/main/uml/api_class_diagram.svg @@ -1 +1 @@ -Keyple - keyple-plugin-java-api - 2.3.+ (2024-03-26)Keyple - keyple-plugin-java-api - 2.3.+ (2024-03-26)org.eclipse.keyple.core.pluginspireaderobservablestateprocessinginsertionremovalfinalPluginApiPropertiesfinalString VERSIONAutonomousObservablePluginApivoid onReaderConnected (Set<ReaderSpi> readers)void onReaderDisconnected (Set<String> readerNames)WaitForCardInsertionAutonomousReaderApivoid onCardInserted ()WaitForCardRemovalAutonomousReaderApivoid onCardRemoved ()CardInsertionWaiterAsynchronousApivoid onCardInserted ()CardRemovalWaiterAsynchronousApivoid onCardRemoved ()«Exception»finalPluginIOExceptionPluginIOException (String message)PluginIOException (String message,Throwable cause)«Exception»finalReaderIOExceptionReaderIOException (String message)ReaderIOException (String message,Throwable cause)«Exception»finalCardIOExceptionCardIOException (String message)CardIOException (String message,Throwable cause)«Exception»finalTaskCanceledExceptionTaskCanceledException (String message)TaskCanceledException (String message,   Throwable cause)PoolPluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPoolPluginName ()PoolPluginSpi getPoolPlugin ()PluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPluginName ()PluginSpi getPlugin ()PoolPluginSpiString getName ()SortedSet<String> getReaderGroupReferences ()PoolReaderSpi allocateReader (String readerGroupReference)void releaseReader (ReaderSpi readerSpi)void onUnregister ()PluginSpiString getName ()Set<ReaderSpi> searchAvailableReaders ()void onUnregister ()ObservablePluginSpiint getMonitoringCycleDuration ()Set<String> searchAvailableReaderNames ()ReaderSpi searchReader (String readerName)AutonomousObservablePluginSpivoid connect (AutonomousObservablePluginApiautonomousObservablePluginApi)void setCallback (AutonomousObservablePluginApi callback)ReaderSpiString getName () void openPhysicalChannel ()void closePhysicalChannel ()boolean isPhysicalChannelOpen () boolean checkCardPresence ()String getPowerOnData ()byte[] transmitApdu (byte[] apduIn)boolean isContactless ()void onUnregister ()PoolReaderSpiObject getSelectedSmartCard ()ConfigurableReaderSpiboolean isProtocolSupported (String readerProtocol)void activateProtocol (String readerProtocol)void deactivateProtocol (String readerProtocol)boolean isCurrentProtocol (String readerProtocol)AutonomousSelectionReaderSpibyte[] openChannelForAid (byte[] dfName, byte isoControlMask)void closeLogicalChannel ()ObservableReaderSpivoid onStartDetection ()void onStopDetection ()WaitForCardRemovalBlockingDuringProcessingSpivoid waitForCardRemovalDuringProcessing ()void stopWaitForCardRemovalDuringProcessing ()DontWaitForCardRemovalDuringProcessingSpiCardPresenceMonitorBlockingSpivoid monitorCardPresenceDuringProcessing ()void stopCardPresenceMonitoringDuringProcessing ()WaitForCardInsertionBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()CardInsertionWaiterBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()WaitForCardInsertionNonBlockingSpiCardInsertionWaiterNonBlockingSpiint getCardInsertionMonitoringSleepDuration ()WaitForCardInsertionAutonomousSpivoid connect (WaitForCardInsertionAutonomousReaderApiwaitForCardInsertionAutonomousReaderApi)CardInsertionWaiterAsynchronousSpivoid setCallback (CardInsertionWaiterAsynchronousApi callback)WaitForCardRemovalBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()CardRemovalWaiterBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()WaitForCardRemovalNonBlockingSpiCardRemovalWaiterNonBlockingSpiint getCardRemovalMonitoringSleepDuration ()WaitForCardRemovalAutonomousSpivoid connect (WaitForCardRemovalAutonomousReaderApiwaitForCardRemovalAutonomousReaderApi)CardRemovalWaiterAsynchronousSpivoid setCallback (CardRemovalWaiterAsynchronousApi callback)provideAPI versionprovideprovideprovideAPI versionprovideprovideuseuseuseuseuse \ No newline at end of file +Keyple - keyple-plugin-java-api - 2.4.+ (2026-03-31)Keyple - keyple-plugin-java-api - 2.4.+ (2026-03-31)org.eclipse.keyple.core.pluginspireaderobservablestateprocessinginsertionremovalfinalPluginApiPropertiesfinalString VERSIONAutonomousObservablePluginApivoid onReaderConnected (Set<ReaderSpi> readers)void onReaderDisconnected (Set<String> readerNames)WaitForCardInsertionAutonomousReaderApivoid onCardInserted ()WaitForCardRemovalAutonomousReaderApivoid onCardRemoved ()CardInsertionWaiterAsynchronousApivoid onCardInserted ()CardRemovalWaiterAsynchronousApivoid onCardRemoved ()«Exception»finalPluginIOExceptionPluginIOException (String message)PluginIOException (String message,Throwable cause)«Exception»finalReaderIOExceptionReaderIOException (String message)ReaderIOException (String message,Throwable cause)«Exception»finalCardIOExceptionCardIOException (String message)CardIOException (String message,Throwable cause)«Exception»finalTaskCanceledExceptionTaskCanceledException (String message)TaskCanceledException (String message,   Throwable cause)PoolPluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPoolPluginName ()PoolPluginSpi getPoolPlugin ()PluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPluginName ()PluginSpi getPlugin ()PoolPluginSpiString getName ()SortedSet<String> getReaderGroupReferences ()PoolReaderSpi allocateReader (String readerGroupReference)void releaseReader (ReaderSpi readerSpi)void onUnregister ()PluginSpiString getName ()Set<ReaderSpi> searchAvailableReaders ()void onUnregister ()ObservablePluginSpiint getMonitoringCycleDuration ()Set<String> searchAvailableReaderNames ()ReaderSpi searchReader (String readerName)AutonomousObservablePluginSpivoid connect (AutonomousObservablePluginApiautonomousObservablePluginApi)void setCallback (AutonomousObservablePluginApi callback)ReaderSpiString getName () void openPhysicalChannel ()void closePhysicalChannel ()boolean isPhysicalChannelOpen () boolean checkCardPresence ()String getPowerOnData ()byte[] transmitApdu (byte[] apduIn)boolean isContactless ()void onUnregister ()PoolReaderSpiObject getSelectedSmartCard ()ConfigurableReaderSpiboolean isProtocolSupported (String readerProtocol)void activateProtocol (String readerProtocol)void deactivateProtocol (String readerProtocol)boolean isCurrentProtocol (String readerProtocol)AutonomousSelectionReaderSpibyte[] openChannelForAid (byte[] dfName, byte isoControlMask)void closeLogicalChannel ()ObservableReaderSpivoid onStartDetection ()void onStopDetection ()WaitForCardRemovalBlockingDuringProcessingSpivoid waitForCardRemovalDuringProcessing ()void stopWaitForCardRemovalDuringProcessing ()DontWaitForCardRemovalDuringProcessingSpiCardPresenceMonitorBlockingSpivoid monitorCardPresenceDuringProcessing ()void stopCardPresenceMonitoringDuringProcessing ()WaitForCardInsertionBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()CardInsertionWaiterBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()WaitForCardInsertionNonBlockingSpiCardInsertionWaiterNonBlockingSpiint getCardInsertionMonitoringSleepDuration ()WaitForCardInsertionAutonomousSpivoid connect (WaitForCardInsertionAutonomousReaderApiwaitForCardInsertionAutonomousReaderApi)CardInsertionWaiterAsynchronousSpivoid setCallback (CardInsertionWaiterAsynchronousApi callback)WaitForCardRemovalBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()CardRemovalWaiterBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()WaitForCardRemovalNonBlockingSpiCardRemovalWaiterNonBlockingSpiint getCardRemovalMonitoringSleepDuration ()WaitForCardRemovalAutonomousSpivoid connect (WaitForCardRemovalAutonomousReaderApiwaitForCardRemovalAutonomousReaderApi)CardRemovalWaiterAsynchronousSpivoid setCallback (CardRemovalWaiterAsynchronousApi callback)provideAPI versionprovideprovideprovideAPI versionprovideprovideuseuseuseuseuse \ No newline at end of file From 250b8b99e871228ddc19729d234e6a23971b870a Mon Sep 17 00:00:00 2001 From: Jean-Pierre Fortune Date: Tue, 31 Mar 2026 17:45:52 +0200 Subject: [PATCH 6/9] release: prepare for 2.4.0-SNAPSHOT version update --- CHANGELOG.md | 3 ++- gradle.properties | 2 +- .../org/eclipse/keyple/core/plugin/PluginApiProperties.java | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 907cfcd..137ad45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `ReaderSpi.getPowerOnData()`: documented lifecycle (meaningful only after a successful `openPhysicalChannel()`) and allowed empty return value. - `CardRemovalWaiterNonBlockingSpi`: the service now uses `checkCardPresence()` instead of - `transmitApdu()` for card removal polling. + `transmitApdu()` for card removal polling. This change is conditioned by the plugin API version: + the new behaviour applies only when the plugin declares API version `2.4` or higher. - Various Javadoc corrections and minor clarifications. ### Fixed - `CardRemovalWaiterAsynchronousApi`: corrected `@link` pointing to a deprecated SPI. diff --git a/gradle.properties b/gradle.properties index d7a3340..64b9946 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ group = org.eclipse.keyple title = Keyple Plugin Java API description = API dedicated to plugins development -version = 2.3.3-SNAPSHOT +version = 2.4.0-SNAPSHOT # Java Configuration javaSourceLevel = 1.8 diff --git a/src/main/java/org/eclipse/keyple/core/plugin/PluginApiProperties.java b/src/main/java/org/eclipse/keyple/core/plugin/PluginApiProperties.java index 27bd0b7..ca46c08 100644 --- a/src/main/java/org/eclipse/keyple/core/plugin/PluginApiProperties.java +++ b/src/main/java/org/eclipse/keyple/core/plugin/PluginApiProperties.java @@ -22,7 +22,7 @@ public final class PluginApiProperties { * * @since 2.0.0 */ - public static final String VERSION = "2.3"; + public static final String VERSION = "2.4"; /** Private constructor */ private PluginApiProperties() {} From ac1319973073b4b4560565d6e8c2ec2a232f15e1 Mon Sep 17 00:00:00 2001 From: Andrei Cristea Date: Mon, 13 Apr 2026 15:59:10 +0200 Subject: [PATCH 7/9] wip --- src/main/uml/api_class_diagram.puml | 14 +++++++++++--- src/main/uml/api_class_diagram.svg | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main/uml/api_class_diagram.puml b/src/main/uml/api_class_diagram.puml index 0304cea..5bba90c 100644 --- a/src/main/uml/api_class_diagram.puml +++ b/src/main/uml/api_class_diagram.puml @@ -155,8 +155,14 @@ package "org.eclipse.keyple.core.plugin" as api { +boolean isCurrentProtocol (String readerProtocol) } +interface AutonomousSelectionReaderSpi <> extends ReaderSpi { - +byte[] openChannelForAid (byte[] dfName, byte isoControlMask) - +void closeLogicalChannel () + +byte[] openChannelForAid (byte[] dfName, byte isoControlMask) + +ChannelDataSpi openChannel (byte[] aid, byte isoControlMask) + +void closeLogicalChannel () + +void closeChannel (int channel) + } + +interface "ChannelDataSpi" as ChannelDataSpi <> { + +int getChannel () + +byte[] getSelectResponse () } package observable { +interface ObservableReaderSpi <> extends api.spi.reader.ReaderSpi { @@ -248,6 +254,8 @@ PoolPluginSpi ..> PoolReaderSpi #C_LINK : provide > AutonomousObservablePluginSpi .up.> AutonomousObservablePluginApi #C_USE : use > +AutonomousSelectionReaderSpi ..> ChannelDataSpi #C_LINK : provide > + WaitForCardInsertionAutonomousSpi ..> WaitForCardInsertionAutonomousReaderApi #C_USE : use > CardInsertionWaiterAsynchronousSpi ..> CardInsertionWaiterAsynchronousApi #C_USE : use > @@ -258,7 +266,7 @@ CardRemovalWaiterAsynchronousSpi ..> CardRemovalWaiterAsynchronousApi #C_USE : u ObservablePluginSpi -[hidden]- reader -AutonomousSelectionReaderSpi -[hidden]- ObservableReaderSpi +AutonomousSelectionReaderSpi -[hidden]-- ObservableReaderSpi ObservableReaderSpi -[hidden]- state diff --git a/src/main/uml/api_class_diagram.svg b/src/main/uml/api_class_diagram.svg index a627d41..c1116c6 100644 --- a/src/main/uml/api_class_diagram.svg +++ b/src/main/uml/api_class_diagram.svg @@ -1 +1 @@ -Keyple - keyple-plugin-java-api - 2.4.+ (2026-03-31)Keyple - keyple-plugin-java-api - 2.4.+ (2026-03-31)org.eclipse.keyple.core.pluginspireaderobservablestateprocessinginsertionremovalfinalPluginApiPropertiesfinalString VERSIONAutonomousObservablePluginApivoid onReaderConnected (Set<ReaderSpi> readers)void onReaderDisconnected (Set<String> readerNames)WaitForCardInsertionAutonomousReaderApivoid onCardInserted ()WaitForCardRemovalAutonomousReaderApivoid onCardRemoved ()CardInsertionWaiterAsynchronousApivoid onCardInserted ()CardRemovalWaiterAsynchronousApivoid onCardRemoved ()«Exception»finalPluginIOExceptionPluginIOException (String message)PluginIOException (String message,Throwable cause)«Exception»finalReaderIOExceptionReaderIOException (String message)ReaderIOException (String message,Throwable cause)«Exception»finalCardIOExceptionCardIOException (String message)CardIOException (String message,Throwable cause)«Exception»finalTaskCanceledExceptionTaskCanceledException (String message)TaskCanceledException (String message,   Throwable cause)PoolPluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPoolPluginName ()PoolPluginSpi getPoolPlugin ()PluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPluginName ()PluginSpi getPlugin ()PoolPluginSpiString getName ()SortedSet<String> getReaderGroupReferences ()PoolReaderSpi allocateReader (String readerGroupReference)void releaseReader (ReaderSpi readerSpi)void onUnregister ()PluginSpiString getName ()Set<ReaderSpi> searchAvailableReaders ()void onUnregister ()ObservablePluginSpiint getMonitoringCycleDuration ()Set<String> searchAvailableReaderNames ()ReaderSpi searchReader (String readerName)AutonomousObservablePluginSpivoid connect (AutonomousObservablePluginApiautonomousObservablePluginApi)void setCallback (AutonomousObservablePluginApi callback)ReaderSpiString getName () void openPhysicalChannel ()void closePhysicalChannel ()boolean isPhysicalChannelOpen () boolean checkCardPresence ()String getPowerOnData ()byte[] transmitApdu (byte[] apduIn)boolean isContactless ()void onUnregister ()PoolReaderSpiObject getSelectedSmartCard ()ConfigurableReaderSpiboolean isProtocolSupported (String readerProtocol)void activateProtocol (String readerProtocol)void deactivateProtocol (String readerProtocol)boolean isCurrentProtocol (String readerProtocol)AutonomousSelectionReaderSpibyte[] openChannelForAid (byte[] dfName, byte isoControlMask)void closeLogicalChannel ()ObservableReaderSpivoid onStartDetection ()void onStopDetection ()WaitForCardRemovalBlockingDuringProcessingSpivoid waitForCardRemovalDuringProcessing ()void stopWaitForCardRemovalDuringProcessing ()DontWaitForCardRemovalDuringProcessingSpiCardPresenceMonitorBlockingSpivoid monitorCardPresenceDuringProcessing ()void stopCardPresenceMonitoringDuringProcessing ()WaitForCardInsertionBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()CardInsertionWaiterBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()WaitForCardInsertionNonBlockingSpiCardInsertionWaiterNonBlockingSpiint getCardInsertionMonitoringSleepDuration ()WaitForCardInsertionAutonomousSpivoid connect (WaitForCardInsertionAutonomousReaderApiwaitForCardInsertionAutonomousReaderApi)CardInsertionWaiterAsynchronousSpivoid setCallback (CardInsertionWaiterAsynchronousApi callback)WaitForCardRemovalBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()CardRemovalWaiterBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()WaitForCardRemovalNonBlockingSpiCardRemovalWaiterNonBlockingSpiint getCardRemovalMonitoringSleepDuration ()WaitForCardRemovalAutonomousSpivoid connect (WaitForCardRemovalAutonomousReaderApiwaitForCardRemovalAutonomousReaderApi)CardRemovalWaiterAsynchronousSpivoid setCallback (CardRemovalWaiterAsynchronousApi callback)provideAPI versionprovideprovideprovideAPI versionprovideprovideuseuseuseuseuse \ No newline at end of file +Keyple - keyple-plugin-java-api - 2.4.+ (2026-03-31)Keyple - keyple-plugin-java-api - 2.4.+ (2026-03-31)org.eclipse.keyple.core.pluginspireaderobservablestateprocessinginsertionremovalfinalPluginApiPropertiesfinalString VERSIONAutonomousObservablePluginApivoid onReaderConnected (Set<ReaderSpi> readers)void onReaderDisconnected (Set<String> readerNames)WaitForCardInsertionAutonomousReaderApivoid onCardInserted ()WaitForCardRemovalAutonomousReaderApivoid onCardRemoved ()CardInsertionWaiterAsynchronousApivoid onCardInserted ()CardRemovalWaiterAsynchronousApivoid onCardRemoved ()«Exception»finalPluginIOExceptionPluginIOException (String message)PluginIOException (String message,Throwable cause)«Exception»finalReaderIOExceptionReaderIOException (String message)ReaderIOException (String message,Throwable cause)«Exception»finalCardIOExceptionCardIOException (String message)CardIOException (String message,Throwable cause)«Exception»finalTaskCanceledExceptionTaskCanceledException (String message)TaskCanceledException (String message,   Throwable cause)PoolPluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPoolPluginName ()PoolPluginSpi getPoolPlugin ()PluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPluginName ()PluginSpi getPlugin ()PoolPluginSpiString getName ()SortedSet<String> getReaderGroupReferences ()PoolReaderSpi allocateReader (String readerGroupReference)void releaseReader (ReaderSpi readerSpi)void onUnregister ()PluginSpiString getName ()Set<ReaderSpi> searchAvailableReaders ()void onUnregister ()ObservablePluginSpiint getMonitoringCycleDuration ()Set<String> searchAvailableReaderNames ()ReaderSpi searchReader (String readerName)AutonomousObservablePluginSpivoid connect (AutonomousObservablePluginApiautonomousObservablePluginApi)void setCallback (AutonomousObservablePluginApi callback)ReaderSpiString getName () void openPhysicalChannel ()void closePhysicalChannel ()boolean isPhysicalChannelOpen () boolean checkCardPresence ()String getPowerOnData ()byte[] transmitApdu (byte[] apduIn)boolean isContactless ()void onUnregister ()PoolReaderSpiObject getSelectedSmartCard ()ConfigurableReaderSpiboolean isProtocolSupported (String readerProtocol)void activateProtocol (String readerProtocol)void deactivateProtocol (String readerProtocol)boolean isCurrentProtocol (String readerProtocol)AutonomousSelectionReaderSpibyte[] openChannelForAid (byte[] dfName, byte isoControlMask)ChannelDataSpi openChannel (byte[] aid, byte isoControlMask)void closeLogicalChannel ()void closeChannel (int channel)ChannelDataSpiint getChannel ()byte[] getSelectResponse ()ObservableReaderSpivoid onStartDetection ()void onStopDetection ()WaitForCardRemovalBlockingDuringProcessingSpivoid waitForCardRemovalDuringProcessing ()void stopWaitForCardRemovalDuringProcessing ()DontWaitForCardRemovalDuringProcessingSpiCardPresenceMonitorBlockingSpivoid monitorCardPresenceDuringProcessing ()void stopCardPresenceMonitoringDuringProcessing ()WaitForCardInsertionBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()CardInsertionWaiterBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()WaitForCardInsertionNonBlockingSpiCardInsertionWaiterNonBlockingSpiint getCardInsertionMonitoringSleepDuration ()WaitForCardInsertionAutonomousSpivoid connect (WaitForCardInsertionAutonomousReaderApiwaitForCardInsertionAutonomousReaderApi)CardInsertionWaiterAsynchronousSpivoid setCallback (CardInsertionWaiterAsynchronousApi callback)WaitForCardRemovalBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()CardRemovalWaiterBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()WaitForCardRemovalNonBlockingSpiCardRemovalWaiterNonBlockingSpiint getCardRemovalMonitoringSleepDuration ()WaitForCardRemovalAutonomousSpivoid connect (WaitForCardRemovalAutonomousReaderApiwaitForCardRemovalAutonomousReaderApi)CardRemovalWaiterAsynchronousSpivoid setCallback (CardRemovalWaiterAsynchronousApi callback)provideAPI versionprovideprovideprovideAPI versionprovideprovideuseprovideuseuseuseuse \ No newline at end of file From b21512f1ff3266c047ddaebf4e37c750556d486b Mon Sep 17 00:00:00 2001 From: Andrei Cristea Date: Fri, 24 Apr 2026 11:41:26 +0200 Subject: [PATCH 8/9] design v2 --- src/main/uml/api_class_diagram.puml | 4 +++- src/main/uml/api_class_diagram.svg | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/uml/api_class_diagram.puml b/src/main/uml/api_class_diagram.puml index 5bba90c..8584bef 100644 --- a/src/main/uml/api_class_diagram.puml +++ b/src/main/uml/api_class_diagram.puml @@ -134,6 +134,7 @@ package "org.eclipse.keyple.core.plugin" as api { package reader { +interface ReaderSpi <> { +String getName () + +boolean isContactless () +void openPhysicalChannel () +void closePhysicalChannel () @@ -142,7 +143,6 @@ package "org.eclipse.keyple.core.plugin" as api { +boolean checkCardPresence () +String getPowerOnData () +byte[] transmitApdu (byte[] apduIn) - +boolean isContactless () +void onUnregister () } +interface "PoolReaderSpi" as PoolReaderSpi <> extends ReaderSpi { @@ -168,6 +168,8 @@ package "org.eclipse.keyple.core.plugin" as api { +interface ObservableReaderSpi <> extends api.spi.reader.ReaderSpi { +void onStartDetection () +void onStopDetection () + + +void deselectCard () } package state { package processing { diff --git a/src/main/uml/api_class_diagram.svg b/src/main/uml/api_class_diagram.svg index c1116c6..c5aa61d 100644 --- a/src/main/uml/api_class_diagram.svg +++ b/src/main/uml/api_class_diagram.svg @@ -1 +1 @@ -Keyple - keyple-plugin-java-api - 2.4.+ (2026-03-31)Keyple - keyple-plugin-java-api - 2.4.+ (2026-03-31)org.eclipse.keyple.core.pluginspireaderobservablestateprocessinginsertionremovalfinalPluginApiPropertiesfinalString VERSIONAutonomousObservablePluginApivoid onReaderConnected (Set<ReaderSpi> readers)void onReaderDisconnected (Set<String> readerNames)WaitForCardInsertionAutonomousReaderApivoid onCardInserted ()WaitForCardRemovalAutonomousReaderApivoid onCardRemoved ()CardInsertionWaiterAsynchronousApivoid onCardInserted ()CardRemovalWaiterAsynchronousApivoid onCardRemoved ()«Exception»finalPluginIOExceptionPluginIOException (String message)PluginIOException (String message,Throwable cause)«Exception»finalReaderIOExceptionReaderIOException (String message)ReaderIOException (String message,Throwable cause)«Exception»finalCardIOExceptionCardIOException (String message)CardIOException (String message,Throwable cause)«Exception»finalTaskCanceledExceptionTaskCanceledException (String message)TaskCanceledException (String message,   Throwable cause)PoolPluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPoolPluginName ()PoolPluginSpi getPoolPlugin ()PluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPluginName ()PluginSpi getPlugin ()PoolPluginSpiString getName ()SortedSet<String> getReaderGroupReferences ()PoolReaderSpi allocateReader (String readerGroupReference)void releaseReader (ReaderSpi readerSpi)void onUnregister ()PluginSpiString getName ()Set<ReaderSpi> searchAvailableReaders ()void onUnregister ()ObservablePluginSpiint getMonitoringCycleDuration ()Set<String> searchAvailableReaderNames ()ReaderSpi searchReader (String readerName)AutonomousObservablePluginSpivoid connect (AutonomousObservablePluginApiautonomousObservablePluginApi)void setCallback (AutonomousObservablePluginApi callback)ReaderSpiString getName () void openPhysicalChannel ()void closePhysicalChannel ()boolean isPhysicalChannelOpen () boolean checkCardPresence ()String getPowerOnData ()byte[] transmitApdu (byte[] apduIn)boolean isContactless ()void onUnregister ()PoolReaderSpiObject getSelectedSmartCard ()ConfigurableReaderSpiboolean isProtocolSupported (String readerProtocol)void activateProtocol (String readerProtocol)void deactivateProtocol (String readerProtocol)boolean isCurrentProtocol (String readerProtocol)AutonomousSelectionReaderSpibyte[] openChannelForAid (byte[] dfName, byte isoControlMask)ChannelDataSpi openChannel (byte[] aid, byte isoControlMask)void closeLogicalChannel ()void closeChannel (int channel)ChannelDataSpiint getChannel ()byte[] getSelectResponse ()ObservableReaderSpivoid onStartDetection ()void onStopDetection ()WaitForCardRemovalBlockingDuringProcessingSpivoid waitForCardRemovalDuringProcessing ()void stopWaitForCardRemovalDuringProcessing ()DontWaitForCardRemovalDuringProcessingSpiCardPresenceMonitorBlockingSpivoid monitorCardPresenceDuringProcessing ()void stopCardPresenceMonitoringDuringProcessing ()WaitForCardInsertionBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()CardInsertionWaiterBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()WaitForCardInsertionNonBlockingSpiCardInsertionWaiterNonBlockingSpiint getCardInsertionMonitoringSleepDuration ()WaitForCardInsertionAutonomousSpivoid connect (WaitForCardInsertionAutonomousReaderApiwaitForCardInsertionAutonomousReaderApi)CardInsertionWaiterAsynchronousSpivoid setCallback (CardInsertionWaiterAsynchronousApi callback)WaitForCardRemovalBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()CardRemovalWaiterBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()WaitForCardRemovalNonBlockingSpiCardRemovalWaiterNonBlockingSpiint getCardRemovalMonitoringSleepDuration ()WaitForCardRemovalAutonomousSpivoid connect (WaitForCardRemovalAutonomousReaderApiwaitForCardRemovalAutonomousReaderApi)CardRemovalWaiterAsynchronousSpivoid setCallback (CardRemovalWaiterAsynchronousApi callback)provideAPI versionprovideprovideprovideAPI versionprovideprovideuseprovideuseuseuseuse \ No newline at end of file +Keyple - keyple-plugin-java-api - 2.4.+ (2026-03-31)Keyple - keyple-plugin-java-api - 2.4.+ (2026-03-31)org.eclipse.keyple.core.pluginspireaderobservablestateprocessinginsertionremovalfinalPluginApiPropertiesfinalString VERSIONAutonomousObservablePluginApivoid onReaderConnected (Set<ReaderSpi> readers)void onReaderDisconnected (Set<String> readerNames)WaitForCardInsertionAutonomousReaderApivoid onCardInserted ()WaitForCardRemovalAutonomousReaderApivoid onCardRemoved ()CardInsertionWaiterAsynchronousApivoid onCardInserted ()CardRemovalWaiterAsynchronousApivoid onCardRemoved ()«Exception»finalPluginIOExceptionPluginIOException (String message)PluginIOException (String message,Throwable cause)«Exception»finalReaderIOExceptionReaderIOException (String message)ReaderIOException (String message,Throwable cause)«Exception»finalCardIOExceptionCardIOException (String message)CardIOException (String message,Throwable cause)«Exception»finalTaskCanceledExceptionTaskCanceledException (String message)TaskCanceledException (String message,   Throwable cause)PoolPluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPoolPluginName ()PoolPluginSpi getPoolPlugin ()PluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPluginName ()PluginSpi getPlugin ()PoolPluginSpiString getName ()SortedSet<String> getReaderGroupReferences ()PoolReaderSpi allocateReader (String readerGroupReference)void releaseReader (ReaderSpi readerSpi)void onUnregister ()PluginSpiString getName ()Set<ReaderSpi> searchAvailableReaders ()void onUnregister ()ObservablePluginSpiint getMonitoringCycleDuration ()Set<String> searchAvailableReaderNames ()ReaderSpi searchReader (String readerName)AutonomousObservablePluginSpivoid connect (AutonomousObservablePluginApiautonomousObservablePluginApi)void setCallback (AutonomousObservablePluginApi callback)ReaderSpiString getName ()boolean isContactless () void openPhysicalChannel ()void closePhysicalChannel ()boolean isPhysicalChannelOpen () boolean checkCardPresence ()String getPowerOnData ()byte[] transmitApdu (byte[] apduIn)void onUnregister ()PoolReaderSpiObject getSelectedSmartCard ()ConfigurableReaderSpiboolean isProtocolSupported (String readerProtocol)void activateProtocol (String readerProtocol)void deactivateProtocol (String readerProtocol)boolean isCurrentProtocol (String readerProtocol)AutonomousSelectionReaderSpibyte[] openChannelForAid (byte[] dfName, byte isoControlMask)ChannelDataSpi openChannel (byte[] aid, byte isoControlMask)void closeLogicalChannel ()void closeChannel (int channel)ChannelDataSpiint getChannel ()byte[] getSelectResponse ()ObservableReaderSpivoid onStartDetection ()void onStopDetection () void deselectCard ()WaitForCardRemovalBlockingDuringProcessingSpivoid waitForCardRemovalDuringProcessing ()void stopWaitForCardRemovalDuringProcessing ()DontWaitForCardRemovalDuringProcessingSpiCardPresenceMonitorBlockingSpivoid monitorCardPresenceDuringProcessing ()void stopCardPresenceMonitoringDuringProcessing ()WaitForCardInsertionBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()CardInsertionWaiterBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()WaitForCardInsertionNonBlockingSpiCardInsertionWaiterNonBlockingSpiint getCardInsertionMonitoringSleepDuration ()WaitForCardInsertionAutonomousSpivoid connect (WaitForCardInsertionAutonomousReaderApiwaitForCardInsertionAutonomousReaderApi)CardInsertionWaiterAsynchronousSpivoid setCallback (CardInsertionWaiterAsynchronousApi callback)WaitForCardRemovalBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()CardRemovalWaiterBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()WaitForCardRemovalNonBlockingSpiCardRemovalWaiterNonBlockingSpiint getCardRemovalMonitoringSleepDuration ()WaitForCardRemovalAutonomousSpivoid connect (WaitForCardRemovalAutonomousReaderApiwaitForCardRemovalAutonomousReaderApi)CardRemovalWaiterAsynchronousSpivoid setCallback (CardRemovalWaiterAsynchronousApi callback)provideAPI versionprovideprovideprovideAPI versionprovideprovideuseprovideuseuseuseuse \ No newline at end of file From ac9b84d3009e33376ebd40538729c390e23fd8b2 Mon Sep 17 00:00:00 2001 From: Andrei Cristea Date: Wed, 29 Apr 2026 17:49:04 +0200 Subject: [PATCH 9/9] wip --- src/main/uml/api_class_diagram.puml | 15 +++++++++------ src/main/uml/api_class_diagram.svg | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/uml/api_class_diagram.puml b/src/main/uml/api_class_diagram.puml index 8584bef..7868b5a 100644 --- a/src/main/uml/api_class_diagram.puml +++ b/src/main/uml/api_class_diagram.puml @@ -1,6 +1,6 @@ @startuml title - Keyple - keyple-plugin-java-api - 2.4.+ (2026-03-31) + Keyple - keyple-plugin-java-api - 2.4.+ (2026-04-29) end title ' == THEME == @@ -154,11 +154,14 @@ package "org.eclipse.keyple.core.plugin" as api { +void deactivateProtocol (String readerProtocol) +boolean isCurrentProtocol (String readerProtocol) } - +interface AutonomousSelectionReaderSpi <> extends ReaderSpi { + +interface "MultichannelReaderSpi" as MultichannelReaderSpi <> extends ReaderSpi { + +ChannelDataSpi openBasicChannel (byte[] aid, byte isoControlMask) + +ChannelDataSpi openLogicalChannel (byte[] aid, byte isoControlMask) + +void closeChannel (int channel) + } + +interface "AutonomousSelectionReaderSpi" as AutonomousSelectionReaderSpi <> extends ReaderSpi { +byte[] openChannelForAid (byte[] dfName, byte isoControlMask) - +ChannelDataSpi openChannel (byte[] aid, byte isoControlMask) +void closeLogicalChannel () - +void closeChannel (int channel) } +interface "ChannelDataSpi" as ChannelDataSpi <> { +int getChannel () @@ -256,7 +259,7 @@ PoolPluginSpi ..> PoolReaderSpi #C_LINK : provide > AutonomousObservablePluginSpi .up.> AutonomousObservablePluginApi #C_USE : use > -AutonomousSelectionReaderSpi ..> ChannelDataSpi #C_LINK : provide > +MultichannelReaderSpi ..> ChannelDataSpi #C_LINK : provide > WaitForCardInsertionAutonomousSpi ..> WaitForCardInsertionAutonomousReaderApi #C_USE : use > CardInsertionWaiterAsynchronousSpi ..> CardInsertionWaiterAsynchronousApi #C_USE : use > @@ -268,7 +271,7 @@ CardRemovalWaiterAsynchronousSpi ..> CardRemovalWaiterAsynchronousApi #C_USE : u ObservablePluginSpi -[hidden]- reader -AutonomousSelectionReaderSpi -[hidden]-- ObservableReaderSpi +MultichannelReaderSpi -[hidden]-- ObservableReaderSpi ObservableReaderSpi -[hidden]- state diff --git a/src/main/uml/api_class_diagram.svg b/src/main/uml/api_class_diagram.svg index c5aa61d..4e00f37 100644 --- a/src/main/uml/api_class_diagram.svg +++ b/src/main/uml/api_class_diagram.svg @@ -1 +1 @@ -Keyple - keyple-plugin-java-api - 2.4.+ (2026-03-31)Keyple - keyple-plugin-java-api - 2.4.+ (2026-03-31)org.eclipse.keyple.core.pluginspireaderobservablestateprocessinginsertionremovalfinalPluginApiPropertiesfinalString VERSIONAutonomousObservablePluginApivoid onReaderConnected (Set<ReaderSpi> readers)void onReaderDisconnected (Set<String> readerNames)WaitForCardInsertionAutonomousReaderApivoid onCardInserted ()WaitForCardRemovalAutonomousReaderApivoid onCardRemoved ()CardInsertionWaiterAsynchronousApivoid onCardInserted ()CardRemovalWaiterAsynchronousApivoid onCardRemoved ()«Exception»finalPluginIOExceptionPluginIOException (String message)PluginIOException (String message,Throwable cause)«Exception»finalReaderIOExceptionReaderIOException (String message)ReaderIOException (String message,Throwable cause)«Exception»finalCardIOExceptionCardIOException (String message)CardIOException (String message,Throwable cause)«Exception»finalTaskCanceledExceptionTaskCanceledException (String message)TaskCanceledException (String message,   Throwable cause)PoolPluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPoolPluginName ()PoolPluginSpi getPoolPlugin ()PluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPluginName ()PluginSpi getPlugin ()PoolPluginSpiString getName ()SortedSet<String> getReaderGroupReferences ()PoolReaderSpi allocateReader (String readerGroupReference)void releaseReader (ReaderSpi readerSpi)void onUnregister ()PluginSpiString getName ()Set<ReaderSpi> searchAvailableReaders ()void onUnregister ()ObservablePluginSpiint getMonitoringCycleDuration ()Set<String> searchAvailableReaderNames ()ReaderSpi searchReader (String readerName)AutonomousObservablePluginSpivoid connect (AutonomousObservablePluginApiautonomousObservablePluginApi)void setCallback (AutonomousObservablePluginApi callback)ReaderSpiString getName ()boolean isContactless () void openPhysicalChannel ()void closePhysicalChannel ()boolean isPhysicalChannelOpen () boolean checkCardPresence ()String getPowerOnData ()byte[] transmitApdu (byte[] apduIn)void onUnregister ()PoolReaderSpiObject getSelectedSmartCard ()ConfigurableReaderSpiboolean isProtocolSupported (String readerProtocol)void activateProtocol (String readerProtocol)void deactivateProtocol (String readerProtocol)boolean isCurrentProtocol (String readerProtocol)AutonomousSelectionReaderSpibyte[] openChannelForAid (byte[] dfName, byte isoControlMask)ChannelDataSpi openChannel (byte[] aid, byte isoControlMask)void closeLogicalChannel ()void closeChannel (int channel)ChannelDataSpiint getChannel ()byte[] getSelectResponse ()ObservableReaderSpivoid onStartDetection ()void onStopDetection () void deselectCard ()WaitForCardRemovalBlockingDuringProcessingSpivoid waitForCardRemovalDuringProcessing ()void stopWaitForCardRemovalDuringProcessing ()DontWaitForCardRemovalDuringProcessingSpiCardPresenceMonitorBlockingSpivoid monitorCardPresenceDuringProcessing ()void stopCardPresenceMonitoringDuringProcessing ()WaitForCardInsertionBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()CardInsertionWaiterBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()WaitForCardInsertionNonBlockingSpiCardInsertionWaiterNonBlockingSpiint getCardInsertionMonitoringSleepDuration ()WaitForCardInsertionAutonomousSpivoid connect (WaitForCardInsertionAutonomousReaderApiwaitForCardInsertionAutonomousReaderApi)CardInsertionWaiterAsynchronousSpivoid setCallback (CardInsertionWaiterAsynchronousApi callback)WaitForCardRemovalBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()CardRemovalWaiterBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()WaitForCardRemovalNonBlockingSpiCardRemovalWaiterNonBlockingSpiint getCardRemovalMonitoringSleepDuration ()WaitForCardRemovalAutonomousSpivoid connect (WaitForCardRemovalAutonomousReaderApiwaitForCardRemovalAutonomousReaderApi)CardRemovalWaiterAsynchronousSpivoid setCallback (CardRemovalWaiterAsynchronousApi callback)provideAPI versionprovideprovideprovideAPI versionprovideprovideuseprovideuseuseuseuse \ No newline at end of file +Keyple - keyple-plugin-java-api - 2.4.+ (2026-04-29)Keyple - keyple-plugin-java-api - 2.4.+ (2026-04-29)org.eclipse.keyple.core.pluginspireaderobservablestateprocessinginsertionremovalfinalPluginApiPropertiesfinalString VERSIONAutonomousObservablePluginApivoid onReaderConnected (Set<ReaderSpi> readers)void onReaderDisconnected (Set<String> readerNames)WaitForCardInsertionAutonomousReaderApivoid onCardInserted ()WaitForCardRemovalAutonomousReaderApivoid onCardRemoved ()CardInsertionWaiterAsynchronousApivoid onCardInserted ()CardRemovalWaiterAsynchronousApivoid onCardRemoved ()«Exception»finalPluginIOExceptionPluginIOException (String message)PluginIOException (String message,Throwable cause)«Exception»finalReaderIOExceptionReaderIOException (String message)ReaderIOException (String message,Throwable cause)«Exception»finalCardIOExceptionCardIOException (String message)CardIOException (String message,Throwable cause)«Exception»finalTaskCanceledExceptionTaskCanceledException (String message)TaskCanceledException (String message,   Throwable cause)PoolPluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPoolPluginName ()PoolPluginSpi getPoolPlugin ()PluginFactorySpiString getPluginApiVersion ()String getCommonApiVersion ()String getPluginName ()PluginSpi getPlugin ()PoolPluginSpiString getName ()SortedSet<String> getReaderGroupReferences ()PoolReaderSpi allocateReader (String readerGroupReference)void releaseReader (ReaderSpi readerSpi)void onUnregister ()PluginSpiString getName ()Set<ReaderSpi> searchAvailableReaders ()void onUnregister ()ObservablePluginSpiint getMonitoringCycleDuration ()Set<String> searchAvailableReaderNames ()ReaderSpi searchReader (String readerName)AutonomousObservablePluginSpivoid connect (AutonomousObservablePluginApiautonomousObservablePluginApi)void setCallback (AutonomousObservablePluginApi callback)ReaderSpiString getName ()boolean isContactless () void openPhysicalChannel ()void closePhysicalChannel ()boolean isPhysicalChannelOpen () boolean checkCardPresence ()String getPowerOnData ()byte[] transmitApdu (byte[] apduIn)void onUnregister ()PoolReaderSpiObject getSelectedSmartCard ()ConfigurableReaderSpiboolean isProtocolSupported (String readerProtocol)void activateProtocol (String readerProtocol)void deactivateProtocol (String readerProtocol)boolean isCurrentProtocol (String readerProtocol)MultichannelReaderSpiChannelDataSpi openBasicChannel (byte[] aid, byte isoControlMask)ChannelDataSpi openLogicalChannel (byte[] aid, byte isoControlMask)void closeChannel (int channel)AutonomousSelectionReaderSpibyte[] openChannelForAid (byte[] dfName, byte isoControlMask)void closeLogicalChannel ()ChannelDataSpiint getChannel ()byte[] getSelectResponse ()ObservableReaderSpivoid onStartDetection ()void onStopDetection () void deselectCard ()WaitForCardRemovalBlockingDuringProcessingSpivoid waitForCardRemovalDuringProcessing ()void stopWaitForCardRemovalDuringProcessing ()DontWaitForCardRemovalDuringProcessingSpiCardPresenceMonitorBlockingSpivoid monitorCardPresenceDuringProcessing ()void stopCardPresenceMonitoringDuringProcessing ()WaitForCardInsertionBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()CardInsertionWaiterBlockingSpivoid waitForCardInsertion ()void stopWaitForCardInsertion ()WaitForCardInsertionNonBlockingSpiCardInsertionWaiterNonBlockingSpiint getCardInsertionMonitoringSleepDuration ()WaitForCardInsertionAutonomousSpivoid connect (WaitForCardInsertionAutonomousReaderApiwaitForCardInsertionAutonomousReaderApi)CardInsertionWaiterAsynchronousSpivoid setCallback (CardInsertionWaiterAsynchronousApi callback)WaitForCardRemovalBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()CardRemovalWaiterBlockingSpivoid waitForCardRemoval ()void stopWaitForCardRemoval ()WaitForCardRemovalNonBlockingSpiCardRemovalWaiterNonBlockingSpiint getCardRemovalMonitoringSleepDuration ()WaitForCardRemovalAutonomousSpivoid connect (WaitForCardRemovalAutonomousReaderApiwaitForCardRemovalAutonomousReaderApi)CardRemovalWaiterAsynchronousSpivoid setCallback (CardRemovalWaiterAsynchronousApi callback)provideAPI versionprovideprovideprovideAPI versionprovideprovideuseprovideuseuseuseuse \ No newline at end of file