All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.keyple.plugin.pcsc.PcscPluginFactoryBuilder Maven / Gradle / Ivy

/* **************************************************************************************
 * Copyright (c) 2021 Calypso Networks Association https://calypsonet.org/
 *
 * See the NOTICE file(s) distributed with this work for additional information
 * regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the terms of the
 * Eclipse Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 ************************************************************************************** */
package org.eclipse.keyple.plugin.pcsc;

import java.security.Provider;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import jnasmartcardio.Smartcardio;
import org.eclipse.keyple.core.util.Assert;

/**
 * Builds instances of {@link PcscPluginFactory} from values configured by the setters.
 *
 * 

The Builder checks if a value configured by a setter satisfies the syntax requirements defined * by the {@link PcscPluginFactoryAdapter} class. * *

Note: all setters of this class are optional.
* It is possible to assign later a protocol type at the reader level using the method {@link * PcscReader#setContactless(boolean)}.
* A set of default protocol identification rules is also proposed. * * @see PcscSupportedContactProtocol * @see PcscSupportedContactlessProtocol * @since 2.0.0 */ public final class PcscPluginFactoryBuilder { private PcscPluginFactoryBuilder() {} /** * Creates builder to build a {@link PcscPluginFactory}. * * @return created builder * @since 2.0.0 */ public static Builder builder() { return new Builder(); } /** * Builder to build a {@link PcscPluginFactory}. * * @since 2.0.0 */ public static class Builder { private static final String DEFAULT_CONTACTLESS_READER_FILTER = "(?i).*(contactless|ask logo|acs acr122).*"; private Pattern contactlessReaderIdentificationFilterPattern = Pattern.compile(DEFAULT_CONTACTLESS_READER_FILTER); private final Map protocolRulesMap; private int cardMonitoringCycleDuration = 500; // default value 500 ms private Provider provider = new Smartcardio(); // jnasmartcardio is the default provider /** * (private)
* Constructs an empty Builder. The default value of all strings is null, the default value of * the map is an empty map. */ private Builder() { protocolRulesMap = new HashMap<>(); } /** * Sets a filter based on regular expressions to make the plugin able to identify a contact * reader from its name. * *

Readers whose names match the provided regular expression will be considered contact type * readers. * *

For example, the string ".*less.*" could identify all readers having "less" in their name * as contactless readers. * *

Names are not always as explicit, so it is sometimes better to test the brand and model. *
* Commonly used contact readers include "Cherry TC" or "Identive".
* Thus, an application using these readers should call this method with {@code ".*(Cherry * TC|Identive).*"} as an argument. * * @param contactReaderIdentificationFilter A string a regular expression. * @return This builder. * @since 2.0.0 * @deprecated Useless method that will be removed soon, see {@link * #useContactlessReaderIdentificationFilter(String)} */ @Deprecated public Builder useContactReaderIdentificationFilter(String contactReaderIdentificationFilter) { return this; } /** * Overwrites the default filter with the provided filter based on regular expressions to make * the plugin able to identify a contact reader from its name. * *

Readers whose names match the provided regular expression will be considered contactless * type readers. * *

The default value is {@value #DEFAULT_CONTACTLESS_READER_FILTER} * * @param contactlessReaderIdentificationFilter A regular expression. * @return This builder. * @throws IllegalArgumentException If the provided string is null, empty or invalid. * @see #useContactReaderIdentificationFilter(String) * @since 2.0.0 */ public Builder useContactlessReaderIdentificationFilter( String contactlessReaderIdentificationFilter) { Assert.getInstance() .notEmpty(contactlessReaderIdentificationFilter, "contactlessReaderIdentificationFilter"); try { this.contactlessReaderIdentificationFilterPattern = Pattern.compile(contactlessReaderIdentificationFilter); } catch (Exception e) { throw new IllegalArgumentException("Bad regular expression.", e); } return this; } /** * Updates a protocol identification rule. * *

A protocol rule is a regular expression contained in a String. * *

    *
  • If a rule already exists for the provided protocol, it is replaced. *
  • If no rule exists for the provided protocol, it is added. *
  • If the rule is null, the protocol is disabled. *
* * @param readerProtocolName A not empty String. * @param protocolRule null to disable the protocol. * @return This builder. * @throws IllegalArgumentException If one of the argument is null or empty * @since 2.0.0 */ public Builder updateProtocolIdentificationRule( String readerProtocolName, String protocolRule) { Assert.getInstance().notEmpty(readerProtocolName, "readerProtocolName"); if (protocolRule == null) { // disable the protocol by defining a regex that always fails. protocolRulesMap.put(readerProtocolName, "X"); } else { protocolRulesMap.put(readerProtocolName, protocolRule); } return this; } /** * Sets the cycle duration for card monitoring (insertion and removal). * *

This parameter allows you to reduce the default value of 500 ms if the underlying layer * doesn't allow multiple accesses to the reader, resulting in high latency in processing. * *

This is particularly useful under Linux when, in observed mode, the APDU processing is not * executed in the same thread as the one used for card detection. A similar case occurs when * several readers are observed simultaneously. * *

The value given here should be determined with care, as it can lead to a significant * increase in the CPU load generated by the application. * * @param cycleDuration The cycle duration for card monitoring, a positive integer in * milliseconds. * @return This builder. * @throws IllegalArgumentException If the provided value is out of range. * @since 2.3.0 */ public Builder setCardMonitoringCycleDuration(int cycleDuration) { Assert.getInstance().greaterOrEqual(cycleDuration, 1, "cycleDuration"); cardMonitoringCycleDuration = cycleDuration; return this; } /** * Replace the default jnasmartcardio provider by the provider given in argument. * * @param provider The provider to use, must not be null. * @return This builder. * @throws IllegalArgumentException If the argument is null. * @since 2.4.0 */ public Builder setProvider(Provider provider) { Assert.getInstance().notNull(provider, "provider"); this.provider = provider; return this; } /** * Returns an instance of PcscPluginFactory created from the fields set on this builder. * *

The type of reader is determined using a regular expression applied to its name.
* The default regular expression is {@value DEFAULT_CONTACTLESS_READER_FILTER}.
* Readers that do not match this regular expression are considered contact type.
* It is possible to redefine the contactless reader filter via the method {@link * #useContactlessReaderIdentificationFilter(String)}. * * @return A {@link PcscPluginFactory} * @since 2.0.0 */ public PcscPluginFactory build() { return new PcscPluginFactoryAdapter( provider, contactlessReaderIdentificationFilterPattern, protocolRulesMap, cardMonitoringCycleDuration); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy