PCSC4Java  0.2
Library PCSC for Java language.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
D:/Affaire/Perso/SmartCardToolBox/pcsc4java-framework-0.2/src/fr/redbilled/security/pcscforjava/TerminalImpl.java
Go to the documentation of this file.
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 }