Path: blob/master/src/java.smartcardio/share/classes/sun/security/smartcardio/TerminalImpl.java
41159 views
/*1* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.smartcardio;2627import java.util.*;2829import javax.smartcardio.*;3031import static sun.security.smartcardio.PCSC.*;3233/**34* CardTerminal implementation.35*36* @since 1.637* @author Andreas Sterbenz38*/39final class TerminalImpl extends CardTerminal {4041// native SCARDCONTEXT42final long contextId;4344// the name of this terminal (native PC/SC name)45final String name;4647private CardImpl card;4849TerminalImpl(long contextId, String name) {50this.contextId = contextId;51this.name = name;52}5354public String getName() {55return name;56}5758public synchronized Card connect(String protocol) throws CardException {59@SuppressWarnings("removal")60SecurityManager sm = System.getSecurityManager();61if (sm != null) {62sm.checkPermission(new CardPermission(name, "connect"));63}64if (card != null) {65if (card.isValid()) {66String cardProto = card.getProtocol();67if (protocol.equals("*") || protocol.equalsIgnoreCase(cardProto)) {68return card;69} else {70throw new CardException("Cannot connect using " + protocol71+ ", connection already established using " + cardProto);72}73} else {74card = null;75}76}77try {78card = new CardImpl(this, protocol);79return card;80} catch (PCSCException e) {81if (e.code == SCARD_W_REMOVED_CARD || e.code == SCARD_E_NO_SMARTCARD) {82throw new CardNotPresentException("No card present", e);83} else {84throw new CardException("connect() failed", e);85}86}87}8889public boolean isCardPresent() throws CardException {90try {91int[] status = SCardGetStatusChange(contextId, 0,92new int[] {SCARD_STATE_UNAWARE}, new String[] {name});93return (status[0] & SCARD_STATE_PRESENT) != 0;94} catch (PCSCException e) {95throw new CardException("isCardPresent() failed", e);96}97}9899private boolean waitForCard(boolean wantPresent, long timeout) throws CardException {100if (timeout < 0) {101throw new IllegalArgumentException("timeout must not be negative");102}103if (timeout == 0) {104timeout = TIMEOUT_INFINITE;105}106int[] status = new int[] {SCARD_STATE_UNAWARE};107String[] readers = new String[] {name};108try {109// check if card status already matches110status = SCardGetStatusChange(contextId, 0, status, readers);111boolean present = (status[0] & SCARD_STATE_PRESENT) != 0;112if (wantPresent == present) {113return true;114}115// no match, wait (until timeout expires)116long end = System.currentTimeMillis() + timeout;117while (wantPresent != present && timeout != 0) {118// set remaining timeout119if (timeout != TIMEOUT_INFINITE) {120timeout = Math.max(end - System.currentTimeMillis(), 0l);121}122status = SCardGetStatusChange(contextId, timeout, status, readers);123present = (status[0] & SCARD_STATE_PRESENT) != 0;124}125return wantPresent == present;126} catch (PCSCException e) {127if (e.code == SCARD_E_TIMEOUT) {128return false;129} else {130throw new CardException("waitForCard() failed", e);131}132}133}134135public boolean waitForCardPresent(long timeout) throws CardException {136return waitForCard(true, timeout);137}138139public boolean waitForCardAbsent(long timeout) throws CardException {140return waitForCard(false, timeout);141}142143public String toString() {144return "PC/SC terminal " + name;145}146}147148149