PCSC4Java
0.2
Library PCSC for Java language.
|
00001 /* 00002 * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. 00003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 00004 * 00005 * This code is free software; you can redistribute it and/or modify it 00006 * under the terms of the GNU General Public License version 2 only, as 00007 * published by the Free Software Foundation. Oracle designates this 00008 * particular file as subject to the "Classpath" exception as provided 00009 * by Oracle in the LICENSE file that accompanied this code. 00010 * 00011 * This code is distributed in the hope that it will be useful, but WITHOUT 00012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 00014 * version 2 for more details (a copy is included in the LICENSE file that 00015 * accompanied this code). 00016 * 00017 * You should have received a copy of the GNU General Public License version 00018 * 2 along with this work; if not, write to the Free Software Foundation, 00019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 00020 * 00021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 00022 * or visit www.oracle.com if you need additional information or have any 00023 * questions. 00024 */ 00025 00026 package fr.redbilled.security.pcscforjava; 00027 00028 00029 import fr.redbilled.pcscforjava.*; 00030 00031 import static fr.redbilled.security.pcscforjava.PCSC.*; 00032 import static fr.redbilled.security.pcscforjava.PCSCDefines.*; 00033 00040 final class TerminalImpl extends CardTerminal { 00041 00042 // native SCARDCONTEXT 00043 long contextId; 00044 00045 // the name of this terminal (native PC/SC name) 00046 final String name; 00047 00048 private CardImpl card; 00049 00050 TerminalImpl(long contextId, String name) { 00051 this.contextId = contextId; 00052 this.name = name; 00053 } 00054 00055 public void setContextId(long contextId) 00056 { 00057 this.contextId = contextId; 00058 } 00059 00060 public String getName() { 00061 return name; 00062 } 00063 00064 public synchronized Card connect(String protocol) throws CardException { 00065 SecurityManager sm = System.getSecurityManager(); 00066 if (sm != null) { 00067 sm.checkPermission(new CardPermission(name, "connect")); 00068 } 00069 if (card != null) { 00070 if (card.isValid()) { 00071 String cardProto = card.getProtocol(); 00072 if (protocol.equals("*") || protocol.equalsIgnoreCase(cardProto)) { 00073 return card; 00074 } else { 00075 throw new CardException("Cannot connect using " + protocol 00076 + ", connection already established using " + cardProto); 00077 } 00078 } else { 00079 card = null; 00080 } 00081 } 00082 try { 00083 card = new CardImpl(this, protocol); 00084 return card; 00085 } catch (PCSCException e) { 00086 if (e.code == SCARD_W_REMOVED_CARD) { 00087 throw new CardNotPresentException("No card present", e); 00088 } else { 00089 throw new CardException("connect() failed", e); 00090 } 00091 } 00092 } 00093 00094 public boolean isCardPresent() throws CardException { 00095 try { 00096 int[] status = SCardGetStatusChange(contextId, 0, 00097 new int[] {SCARD_STATE_UNAWARE}, new String[] {name}); 00098 if(status != null) 00099 return (status[0] & SCARD_STATE_PRESENT) != 0; 00100 else 00101 return false; 00102 } catch (PCSCException e) { 00103 System.err.println(this.getName() + " isCardPresent " + e); 00104 throw new CardException("isCardPresent() failed", e); 00105 } 00106 } 00107 00108 private boolean waitForCard(boolean wantPresent, long timeout) 00109 throws CardException 00110 { 00111 if (timeout < 0) { 00112 throw new IllegalArgumentException("timeout must not be negative"); 00113 } 00114 if (timeout == 0) { 00115 timeout = TIMEOUT_INFINITE; 00116 } 00117 int[] status = new int[] {SCARD_STATE_UNAWARE}; 00118 String[] readers = new String[] {name}; 00119 try { 00120 // check if card status already matches 00121 status = SCardGetStatusChange(contextId, 0, status, readers); 00122 boolean present; 00123 if(status != null) 00124 present = (status[0] & SCARD_STATE_PRESENT) != 0; 00125 else 00126 present = !wantPresent; 00127 00128 if (wantPresent == present) { 00129 return true; 00130 } 00131 00132 // no match, wait 00133 status = SCardGetStatusChange(contextId, timeout, status, readers); 00134 if(status != null) 00135 present = (status[0] & SCARD_STATE_PRESENT) != 0; 00136 else 00137 present = !wantPresent; 00138 // should never happen 00139 if (wantPresent != present) { 00140 //throw new CardException("wait mismatch"); 00141 return false; 00142 } 00143 return true; 00144 } catch (PCSCException e) { 00145 if (e.code == SCARD_E_TIMEOUT) { 00146 return false; 00147 } else { 00148 throw new CardException("waitForCard: " + e.getMessage()); 00149 } 00150 } 00151 } 00152 00153 public boolean waitForCardPresent(long timeout) throws CardException { 00154 return waitForCard(true, timeout); 00155 } 00156 00157 public boolean waitForCardAbsent(long timeout) throws CardException { 00158 return waitForCard(false, timeout); 00159 } 00160 00161 public String toString() { 00162 return "PC/SC terminal " + name; 00163 } 00164 00165 @Override 00166 public synchronized void cancelOperation() throws CardException { 00167 try { 00168 SCardCancel(contextId); 00169 } 00170 catch(PCSCException ex) 00171 { 00172 throw new CardException("cancelOperation: " + ex.getMessage()); 00173 } 00174 } 00175 00176 @Override 00177 public synchronized byte[][] getCardStatus() throws CardException { 00178 byte[][] _ppBResult = new byte[3][]; 00179 byte[] _pBStatus = new byte[2]; 00180 byte[] _pBAtr; 00181 00182 try { _pBAtr = SCardStatus(contextId, _pBStatus); } 00183 catch (PCSCException ex) 00184 { throw new CardException("getCardStatus: " + ex.getMessage()); } 00185 00186 _ppBResult[0] = _pBAtr; 00187 00188 _ppBResult[1] = new byte[1]; 00189 _ppBResult[1][0] = _pBStatus[0]; 00190 _ppBResult[2] = new byte[1]; 00191 _ppBResult[2][0] = _pBStatus[1]; 00192 00193 return _ppBResult; 00194 } 00195 00196 synchronized void notifyDisconnection() 00197 { 00198 this.card = null; 00199 } 00200 }