0N/A/*
4404N/A * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.security.smartcardio;
0N/A
0N/Aimport java.util.*;
0N/A
0N/Aimport javax.smartcardio.*;
0N/A
0N/Aimport static sun.security.smartcardio.PCSC.*;
0N/A
0N/A/**
0N/A * CardTerminal implementation.
0N/A *
0N/A * @since 1.6
0N/A * @author Andreas Sterbenz
0N/A */
0N/Afinal class TerminalImpl extends CardTerminal {
0N/A
0N/A // native SCARDCONTEXT
0N/A final long contextId;
0N/A
0N/A // the name of this terminal (native PC/SC name)
0N/A final String name;
0N/A
0N/A private CardImpl card;
0N/A
0N/A TerminalImpl(long contextId, String name) {
0N/A this.contextId = contextId;
0N/A this.name = name;
0N/A }
0N/A
0N/A public String getName() {
0N/A return name;
0N/A }
0N/A
0N/A public synchronized Card connect(String protocol) throws CardException {
0N/A SecurityManager sm = System.getSecurityManager();
0N/A if (sm != null) {
0N/A sm.checkPermission(new CardPermission(name, "connect"));
0N/A }
0N/A if (card != null) {
0N/A if (card.isValid()) {
0N/A String cardProto = card.getProtocol();
0N/A if (protocol.equals("*") || protocol.equalsIgnoreCase(cardProto)) {
0N/A return card;
0N/A } else {
0N/A throw new CardException("Cannot connect using " + protocol
0N/A + ", connection already established using " + cardProto);
0N/A }
0N/A } else {
0N/A card = null;
0N/A }
0N/A }
0N/A try {
0N/A card = new CardImpl(this, protocol);
0N/A return card;
0N/A } catch (PCSCException e) {
0N/A if (e.code == SCARD_W_REMOVED_CARD) {
0N/A throw new CardNotPresentException("No card present", e);
0N/A } else {
0N/A throw new CardException("connect() failed", e);
0N/A }
0N/A }
0N/A }
0N/A
0N/A public boolean isCardPresent() throws CardException {
0N/A try {
0N/A int[] status = SCardGetStatusChange(contextId, 0,
0N/A new int[] {SCARD_STATE_UNAWARE}, new String[] {name});
0N/A return (status[0] & SCARD_STATE_PRESENT) != 0;
0N/A } catch (PCSCException e) {
0N/A throw new CardException("isCardPresent() failed", e);
0N/A }
0N/A }
0N/A
0N/A private boolean waitForCard(boolean wantPresent, long timeout) throws CardException {
0N/A if (timeout < 0) {
0N/A throw new IllegalArgumentException("timeout must not be negative");
0N/A }
0N/A if (timeout == 0) {
0N/A timeout = TIMEOUT_INFINITE;
0N/A }
0N/A int[] status = new int[] {SCARD_STATE_UNAWARE};
0N/A String[] readers = new String[] {name};
0N/A try {
0N/A // check if card status already matches
0N/A status = SCardGetStatusChange(contextId, 0, status, readers);
0N/A boolean present = (status[0] & SCARD_STATE_PRESENT) != 0;
0N/A if (wantPresent == present) {
0N/A return true;
0N/A }
4404N/A // no match, wait (until timeout expires)
4404N/A long end = System.currentTimeMillis() + timeout;
4404N/A while (wantPresent != present && timeout != 0) {
4404N/A // set remaining timeout
4404N/A if (timeout != TIMEOUT_INFINITE) {
4404N/A timeout = Math.max(end - System.currentTimeMillis(), 0l);
4404N/A }
4404N/A status = SCardGetStatusChange(contextId, timeout, status, readers);
4404N/A present = (status[0] & SCARD_STATE_PRESENT) != 0;
0N/A }
4404N/A return wantPresent == present;
0N/A } catch (PCSCException e) {
0N/A if (e.code == SCARD_E_TIMEOUT) {
0N/A return false;
0N/A } else {
0N/A throw new CardException("waitForCard() failed", e);
0N/A }
0N/A }
0N/A }
0N/A
0N/A public boolean waitForCardPresent(long timeout) throws CardException {
0N/A return waitForCard(true, timeout);
0N/A }
0N/A
0N/A public boolean waitForCardAbsent(long timeout) throws CardException {
0N/A return waitForCard(false, timeout);
0N/A }
0N/A
0N/A public String toString() {
0N/A return "PC/SC terminal " + name;
0N/A }
0N/A}