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