/* | 
|
 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. | 
|
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
|
 * | 
|
 * This code is free software; you can redistribute it and/or modify it | 
|
 * under the terms of the GNU General Public License version 2 only, as | 
|
 * published by the Free Software Foundation.  Oracle designates this | 
|
 * particular file as subject to the "Classpath" exception as provided | 
|
 * by Oracle in the LICENSE file that accompanied this code. | 
|
 * | 
|
 * This code is distributed in the hope that it will be useful, but WITHOUT | 
|
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
|
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
|
 * version 2 for more details (a copy is included in the LICENSE file that | 
|
 * accompanied this code). | 
|
 * | 
|
 * You should have received a copy of the GNU General Public License version | 
|
 * 2 along with this work; if not, write to the Free Software Foundation, | 
|
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
|
 * | 
|
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 
|
 * or visit www.oracle.com if you need additional information or have any | 
|
 * questions. | 
|
*/  | 
|
package javax.smartcardio;  | 
|
import java.util.*;  | 
|
/** | 
|
 * The set of terminals supported by a TerminalFactory. | 
|
 * This class allows applications to enumerate the available CardTerminals, | 
|
 * obtain a specific CardTerminal, or wait for the insertion or removal of | 
|
 * cards. | 
|
 * | 
|
 * <p>This class is multi-threading safe and can be used by multiple | 
|
 * threads concurrently. However, this object keeps track of the card | 
|
 * presence state of each of its terminals. Multiple objects should be used | 
|
 * if independent calls to {@linkplain #waitForChange} are required. | 
|
 * | 
|
 * <p>Applications can obtain instances of this class by calling | 
|
 * {@linkplain TerminalFactory#terminals}. | 
|
 * | 
|
 * @see TerminalFactory | 
|
 * @see CardTerminal | 
|
 * | 
|
 * @since   1.6 | 
|
 * @author  Andreas Sterbenz | 
|
 * @author  JSR 268 Expert Group | 
|
*/  | 
|
public abstract class CardTerminals { | 
|
    /** | 
|
     * Constructs a new CardTerminals object. | 
|
     * | 
|
     * <p>This constructor is called by subclasses only. Application should | 
|
     * call {@linkplain TerminalFactory#terminals} | 
|
     * to obtain a CardTerminals object. | 
|
*/  | 
|
    protected CardTerminals() { | 
|
// empty  | 
|
}  | 
|
    /** | 
|
     * Returns an unmodifiable list of all available terminals. | 
|
     * | 
|
     * @return an unmodifiable list of all available terminals. | 
|
     * | 
|
     * @throws CardException if the card operation failed | 
|
*/  | 
|
public List<CardTerminal> list() throws CardException {  | 
|
return list(State.ALL);  | 
|
}  | 
|
    /** | 
|
     * Returns an unmodifiable list of all terminals matching the specified | 
|
     * state. | 
|
     * | 
|
     * <p>If state is {@link State#ALL State.ALL}, this method returns | 
|
     * all CardTerminals encapsulated by this object. | 
|
     * If state is {@link State#CARD_PRESENT State.CARD_PRESENT} or | 
|
     * {@link State#CARD_ABSENT State.CARD_ABSENT}, it returns all | 
|
     * CardTerminals where a card is currently present or absent, respectively. | 
|
     * | 
|
     * <p>If state is {@link State#CARD_INSERTION State.CARD_INSERTION} or | 
|
     * {@link State#CARD_REMOVAL State.CARD_REMOVAL}, it returns all | 
|
     * CardTerminals for which an insertion (or removal, respectively) | 
|
     * was detected during the last call to {@linkplain #waitForChange}. | 
|
     * If <code>waitForChange()</code> has not been called on this object, | 
|
     * <code>CARD_INSERTION</code> is equivalent to <code>CARD_PRESENT</code> | 
|
     * and <code>CARD_REMOVAL</code> is equivalent to <code>CARD_ABSENT</code>. | 
|
     * For an example of the use of <code>CARD_INSERTION</code>, | 
|
     * see {@link #waitForChange}. | 
|
     * | 
|
     * @param state the State | 
|
     * @return an unmodifiable list of all terminals matching the specified | 
|
     *   attribute. | 
|
     * | 
|
     * @throws NullPointerException if attr is null | 
|
     * @throws CardException if the card operation failed | 
|
*/  | 
|
public abstract List<CardTerminal> list(State state) throws CardException;  | 
|
    /** | 
|
     * Returns the terminal with the specified name or null if no such | 
|
     * terminal exists. | 
|
     * | 
|
     * @return the terminal with the specified name or null if no such | 
|
     * terminal exists. | 
|
     * | 
|
     * @throws NullPointerException if name is null | 
|
*/  | 
|
public CardTerminal getTerminal(String name) {  | 
|
if (name == null) {  | 
|
throw new NullPointerException();  | 
|
}  | 
|
        try { | 
|
for (CardTerminal terminal : list()) {  | 
|
if (terminal.getName().equals(name)) {  | 
|
return terminal;  | 
|
}  | 
|
}  | 
|
return null;  | 
|
} catch (CardException e) {  | 
|
return null;  | 
|
}  | 
|
}  | 
|
    /** | 
|
     * Waits for card insertion or removal in any of the terminals of this | 
|
     * object. | 
|
     * | 
|
     * <p>This call is equivalent to calling | 
|
     * {@linkplain #waitForChange(long) waitForChange(0)}. | 
|
     * | 
|
     * @throws IllegalStateException if this <code>CardTerminals</code> | 
|
     *   object does not contain any terminals | 
|
     * @throws CardException if the card operation failed | 
|
*/  | 
|
public void waitForChange() throws CardException {  | 
|
waitForChange(0);  | 
|
}  | 
|
    /** | 
|
     * Waits for card insertion or removal in any of the terminals of this | 
|
     * object or until the timeout expires. | 
|
     * | 
|
     * <p>This method examines each CardTerminal of this object. | 
|
     * If a card was inserted into or removed from a CardTerminal since the | 
|
     * previous call to <code>waitForChange()</code>, it returns | 
|
     * immediately. | 
|
     * Otherwise, or if this is the first call to <code>waitForChange()</code> | 
|
     * on this object, it blocks until a card is inserted into or removed from | 
|
     * a CardTerminal. | 
|
     * | 
|
     * <p>If <code>timeout</code> is greater than 0, the method returns after | 
|
     * <code>timeout</code> milliseconds even if there is no change in state. | 
|
     * In that case, this method returns <code>false</code>; otherwise it | 
|
     * returns <code>true</code>. | 
|
     * | 
|
     * <p>This method is often used in a loop in combination with | 
|
     * {@link #list(CardTerminals.State) list(State.CARD_INSERTION)}, | 
|
     * for example: | 
|
     * <pre> | 
|
     *  TerminalFactory factory = ...; | 
|
     *  CardTerminals terminals = factory.terminals(); | 
|
     *  while (true) { | 
|
     *      for (CardTerminal terminal : terminals.list(CARD_INSERTION)) { | 
|
     *          // examine Card in terminal, return if it matches | 
|
     *      } | 
|
     *      terminals.waitForChange(); | 
|
     *  }</pre> | 
|
     * | 
|
     * @param timeout if positive, block for up to <code>timeout</code> | 
|
     *   milliseconds; if zero, block indefinitely; must not be negative | 
|
     * @return false if the method returns due to an expired timeout, | 
|
     *   true otherwise. | 
|
     * | 
|
     * @throws IllegalStateException if this <code>CardTerminals</code> | 
|
     *   object does not contain any terminals | 
|
     * @throws IllegalArgumentException if timeout is negative | 
|
     * @throws CardException if the card operation failed | 
|
*/  | 
|
public abstract boolean waitForChange(long timeout) throws CardException;  | 
|
    /** | 
|
     * Enumeration of attributes of a CardTerminal. | 
|
     * It is used as a parameter to the {@linkplain CardTerminals#list} method. | 
|
     * | 
|
     * @since 1.6 | 
|
*/  | 
|
    public static enum State { | 
|
        /** | 
|
         * All CardTerminals. | 
|
*/  | 
|
ALL,  | 
|
        /** | 
|
         * CardTerminals in which a card is present. | 
|
*/  | 
|
CARD_PRESENT,  | 
|
        /** | 
|
         * CardTerminals in which a card is not present. | 
|
*/  | 
|
CARD_ABSENT,  | 
|
        /** | 
|
         * CardTerminals for which a card insertion was detected during the | 
|
         * latest call to {@linkplain State#waitForChange waitForChange()} | 
|
         * call. | 
|
*/  | 
|
CARD_INSERTION,  | 
|
        /** | 
|
         * CardTerminals for which a card removal was detected during the | 
|
         * latest call to {@linkplain State#waitForChange waitForChange()} | 
|
         * call. | 
|
*/  | 
|
CARD_REMOVAL,  | 
|
}  | 
|
}  |