1 /* 2 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.smartcardio; 27 28 import java.util.*; 29 30 /** 31 * The set of terminals supported by a TerminalFactory. 32 * This class allows applications to enumerate the available CardTerminals, 33 * obtain a specific CardTerminal, or wait for the insertion or removal of 34 * cards. 35 * 36 * <p>This class is multi-threading safe and can be used by multiple 37 * threads concurrently. However, this object keeps track of the card 38 * presence state of each of its terminals. Multiple objects should be used 39 * if independent calls to {@linkplain #waitForChange} are required. 40 * 41 * <p>Applications can obtain instances of this class by calling 42 * {@linkplain TerminalFactory#terminals}. 43 * 44 * @see TerminalFactory 45 * @see CardTerminal 46 * 47 * @since 1.6 48 * @author Andreas Sterbenz 49 * @author JSR 268 Expert Group 50 */ 51 public abstract class CardTerminals { 52 53 /** 54 * Constructs a new CardTerminals object. 55 * 56 * <p>This constructor is called by subclasses only. Application should 57 * call {@linkplain TerminalFactory#terminals} 58 * to obtain a CardTerminals object. 59 */ CardTerminals()60 protected CardTerminals() { 61 // empty 62 } 63 64 /** 65 * Returns an unmodifiable list of all available terminals. 66 * 67 * @return an unmodifiable list of all available terminals. 68 * 69 * @throws CardException if the card operation failed 70 */ list()71 public List<CardTerminal> list() throws CardException { 72 return list(State.ALL); 73 } 74 75 /** 76 * Returns an unmodifiable list of all terminals matching the specified 77 * state. 78 * 79 * <p>If state is {@link State#ALL State.ALL}, this method returns 80 * all CardTerminals encapsulated by this object. 81 * If state is {@link State#CARD_PRESENT State.CARD_PRESENT} or 82 * {@link State#CARD_ABSENT State.CARD_ABSENT}, it returns all 83 * CardTerminals where a card is currently present or absent, respectively. 84 * 85 * <p>If state is {@link State#CARD_INSERTION State.CARD_INSERTION} or 86 * {@link State#CARD_REMOVAL State.CARD_REMOVAL}, it returns all 87 * CardTerminals for which an insertion (or removal, respectively) 88 * was detected during the last call to {@linkplain #waitForChange}. 89 * If <code>waitForChange()</code> has not been called on this object, 90 * <code>CARD_INSERTION</code> is equivalent to <code>CARD_PRESENT</code> 91 * and <code>CARD_REMOVAL</code> is equivalent to <code>CARD_ABSENT</code>. 92 * For an example of the use of <code>CARD_INSERTION</code>, 93 * see {@link #waitForChange}. 94 * 95 * @param state the State 96 * @return an unmodifiable list of all terminals matching the specified 97 * attribute. 98 * 99 * @throws NullPointerException if attr is null 100 * @throws CardException if the card operation failed 101 */ list(State state)102 public abstract List<CardTerminal> list(State state) throws CardException; 103 104 /** 105 * Returns the terminal with the specified name or null if no such 106 * terminal exists. 107 * 108 * @return the terminal with the specified name or null if no such 109 * terminal exists. 110 * 111 * @throws NullPointerException if name is null 112 */ getTerminal(String name)113 public CardTerminal getTerminal(String name) { 114 if (name == null) { 115 throw new NullPointerException(); 116 } 117 try { 118 for (CardTerminal terminal : list()) { 119 if (terminal.getName().equals(name)) { 120 return terminal; 121 } 122 } 123 return null; 124 } catch (CardException e) { 125 return null; 126 } 127 } 128 129 /** 130 * Waits for card insertion or removal in any of the terminals of this 131 * object. 132 * 133 * <p>This call is equivalent to calling 134 * {@linkplain #waitForChange(long) waitForChange(0)}. 135 * 136 * @throws IllegalStateException if this <code>CardTerminals</code> 137 * object does not contain any terminals 138 * @throws CardException if the card operation failed 139 */ waitForChange()140 public void waitForChange() throws CardException { 141 waitForChange(0); 142 } 143 144 /** 145 * Waits for card insertion or removal in any of the terminals of this 146 * object or until the timeout expires. 147 * 148 * <p>This method examines each CardTerminal of this object. 149 * If a card was inserted into or removed from a CardTerminal since the 150 * previous call to <code>waitForChange()</code>, it returns 151 * immediately. 152 * Otherwise, or if this is the first call to <code>waitForChange()</code> 153 * on this object, it blocks until a card is inserted into or removed from 154 * a CardTerminal. 155 * 156 * <p>If <code>timeout</code> is greater than 0, the method returns after 157 * <code>timeout</code> milliseconds even if there is no change in state. 158 * In that case, this method returns <code>false</code>; otherwise it 159 * returns <code>true</code>. 160 * 161 * <p>This method is often used in a loop in combination with 162 * {@link #list(CardTerminals.State) list(State.CARD_INSERTION)}, 163 * for example: 164 * <pre> 165 * TerminalFactory factory = ...; 166 * CardTerminals terminals = factory.terminals(); 167 * while (true) { 168 * for (CardTerminal terminal : terminals.list(CARD_INSERTION)) { 169 * // examine Card in terminal, return if it matches 170 * } 171 * terminals.waitForChange(); 172 * }</pre> 173 * 174 * @param timeout if positive, block for up to <code>timeout</code> 175 * milliseconds; if zero, block indefinitely; must not be negative 176 * @return false if the method returns due to an expired timeout, 177 * true otherwise. 178 * 179 * @throws IllegalStateException if this <code>CardTerminals</code> 180 * object does not contain any terminals 181 * @throws IllegalArgumentException if timeout is negative 182 * @throws CardException if the card operation failed 183 */ waitForChange(long timeout)184 public abstract boolean waitForChange(long timeout) throws CardException; 185 186 /** 187 * Enumeration of attributes of a CardTerminal. 188 * It is used as a parameter to the {@linkplain CardTerminals#list} method. 189 * 190 * @since 1.6 191 */ 192 public static enum State { 193 /** 194 * All CardTerminals. 195 */ 196 ALL, 197 /** 198 * CardTerminals in which a card is present. 199 */ 200 CARD_PRESENT, 201 /** 202 * CardTerminals in which a card is not present. 203 */ 204 CARD_ABSENT, 205 /** 206 * CardTerminals for which a card insertion was detected during the 207 * latest call to {@linkplain State#waitForChange waitForChange()} 208 * call. 209 */ 210 CARD_INSERTION, 211 /** 212 * CardTerminals for which a card removal was detected during the 213 * latest call to {@linkplain State#waitForChange waitForChange()} 214 * call. 215 */ 216 CARD_REMOVAL, 217 } 218 219 } 220