package purseclient;

import java.lang.*;
import java.io.IOException;
import java.io.FileNotFoundException;
import opencard.core.terminal.*;
import opencard.core.util.*;
import opencard.core.service.*;
import opencard.opt.util.*;
/**
 * <p>Title: e-Purse</p>
 *
 * <p>Description: Java Card e-Purse with Bonus feature</p>
 *
 * <p>Copyright: Copyright (c) 2007</p>
 *
 * <p>Company: Aristotele University Thessaloniki</p>
 *
 * @author Vasileios Almaliotis, Aleksandos Loizidis
 * @version 1.0
 */
public class PurseCommunication {
    private static SmartCard myCard;
    private static CardRequest cr;
    private static PassThruCardService myCS;

    final static short MAX_AMOUNT = (short)1000; // for whatever reason

    //CLA byte code
    final static byte PURSE_CLA =(byte)0x80;

    //INS byte code
    final static byte VALIDATE = (byte) 0x21;
    final static byte CREDIT = (byte) 0x22;
    final static byte DEBIT = (byte) 0x23;
    final static byte GET_BALANCE = (byte) 0x24;
    final static byte GET_ACCOUNT_NUMBER = (byte) 0x25;
    final static byte GET_USER_NAME = (byte) 0x26;
    final static byte GET_USER_ADDRESS = (byte) 0x27;
    final static byte GET_USER_SURNAME = (byte) 0x28;
    final static byte SET_ACCOUNT_NUMBER = (byte) 0x29;
    final static byte SET_USER_ADDRESS = (byte) 0x30;
    final static byte SET_USER_NAME = (byte) 0x31;
    final static byte SET_USER_SURNAME = (byte) 0x32;
    final static byte SET_USER_PIN = (byte) 0x33;

    //SW byte code
    final static short SW_OK = (short)0x9000;
    final static short SW_UNDERFLOW = (short)0x9100;
    final static short SW_OVERFLOW  = (short)0x9101;
    final static short SW_BAD_ARGUMENT  = (short)0x9102;
    final static short SW_WRONG_LE = (short)0x9103;
    final static short SW_NOT_VERIFIED = (short)0x9104;
    final static short SW_VERIFICATION_FAILED = (short)0x9105;
    final static short SW_TRANSACTION_OVERFLOW = (short)0x9106;
    final static short SW_NO_DATA = (short)0x9107;
    final static short SW_APPLET_LOCKED = (short)0x9108;
    final static short SW_APPLET_NOT_FOUND = (short)0x6D00;
    final static short SW_FALSE = (short)0x6999;
    final static short SW_INS_NOT_SUPPORTED = (short)0x6D00;


    public PurseCommunication() {
        System.getProperties().setProperty("user.dir", "C:/");
        try {
            jbInit();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void main(String[] args) {
        PurseCommunication pursecommunication = new PurseCommunication();
    }

    public void startFramework()
    throws IOException,
    ClassNotFoundException,
    FileNotFoundException{
        try{
            SmartCard.start();
        }catch(CardTerminalException e){
            throw new IOException("Connection fails");
        }catch(ClassNotFoundException e){
            throw new ClassNotFoundException("Unable to find Class");
        }catch(OpenCardPropertyLoadingException e){
            throw new FileNotFoundException("Unable to find OpenCard properties file");
        }catch(CardServiceException e){
            throw new IOException("Card Service not found");
        }
    }

    public void stopFramework()
    throws IOException{
        try{
            SmartCard.shutdown();
        }catch(CardTerminalException e){
            throw new IOException("Unable to disconnect");
        }
    }

    public void connectToCard()
    throws IOException,
    ClassNotFoundException{
        try{
            cr = new CardRequest(CardRequest.ANYCARD, null, PassThruCardService.class);
            myCard = SmartCard.waitForCard(cr);
            myCS = (PassThruCardService) myCard.getCardService(PassThruCardService.class, true);
        }catch(CardTerminalException e){
            throw new IOException("Connection fails");
        }catch(CardServiceException e){
            throw new IOException("Unable to find the requested service");
        }catch(ClassNotFoundException e){
            throw new ClassNotFoundException("Unable to find Class");
        }catch(NullPointerException e){
            throw new ClassNotFoundException("Unable to find Class");
        }


    }

    public void selectApplet(byte[] appletAID)
    throws RuntimeException,
    IOException,
    IllegalStateException{
        byte appLength = (byte)(appletAID.length & 0xFF);
        try{
            CommandAPDU selectAppletAPDU = new CommandAPDU(6 + appletAID.length);
            selectAppletAPDU.append((byte) 0x00);
            selectAppletAPDU.append((byte) 0xA4);
            selectAppletAPDU.append((byte) 0x04);
            selectAppletAPDU.append((byte) 0x00);
            selectAppletAPDU.append((byte) appLength);
            selectAppletAPDU.append(appletAID);
            selectAppletAPDU.append((byte) 0x05);
            ResponseAPDU resp = myCS.sendCommandAPDU(selectAppletAPDU);
            System.out.println(selectAppletAPDU.toString()+resp.toString());
            short status = (short)resp.sw();
            switch(status){
            case SW_OK:
                return;
            case SW_FALSE:
                throw new IllegalStateException("Applet locked");
            case SW_APPLET_NOT_FOUND:
                throw new IllegalArgumentException("Applet not found");
            default:
                throw new RuntimeException("Unknown Runtime Exception");
            }
        }catch(CardTerminalException e){
            throw new IOException("Connection fails");
        }
    }

    public boolean validate(char[] PIN)
    throws IOException,
    IllegalArgumentException,
    RuntimeException{
        byte[] PINBytes = String.valueOf(PIN).getBytes();

        CommandAPDU validateAPDU = new CommandAPDU(6+PINBytes.length);
        validateAPDU.setLength(0);
        validateAPDU.append(PURSE_CLA);
        validateAPDU.append(VALIDATE);
        validateAPDU.append((byte)0x00);
        validateAPDU.append((byte)0x00);
        validateAPDU.append((byte)(PINBytes.length & 0xFF));
        validateAPDU.append(PINBytes);
        validateAPDU.append((byte)0x00);
        try{
            ResponseAPDU resp = myCS.sendCommandAPDU(validateAPDU);
            System.out.println(validateAPDU.toString()+resp.toString());
            short status = (short)resp.sw();
            switch(status){
            case SW_OK:
                return true;
            case SW_VERIFICATION_FAILED:
                return false;
            case SW_APPLET_LOCKED:
                throw new IllegalArgumentException("Applet locked");
            case SW_FALSE:
                throw new IllegalArgumentException("CLA not supporeted");
            case SW_INS_NOT_SUPPORTED:
                throw new IllegalArgumentException("INS not supported");
            default:
                throw new RuntimeException("Unknown Runtime Exception");
            }
        }catch(CardTerminalException e){
            throw new IOException("Connection fails");
        }catch(NullPointerException e){
            throw new IOException("Card service must been initialized first");
        }
    }

    public boolean changePIN(char[] oldPIN, char[] newPIN)
    throws IOException,
    IllegalArgumentException,
    RuntimeException{
        byte[] oldPINBytes = String.valueOf(oldPIN).getBytes();
        byte[] newPINBytes = String.valueOf(newPIN).getBytes();

        int totalLength = oldPINBytes.length + newPINBytes.length;

        CommandAPDU changePINAPDU = new CommandAPDU(6+totalLength);

        changePINAPDU.append(PURSE_CLA);
        changePINAPDU.append(SET_USER_PIN);
        changePINAPDU.append((byte)(oldPINBytes.length & 0xFF));
        changePINAPDU.append((byte)(newPINBytes.length & 0xFF));
        changePINAPDU.append((byte)(totalLength & 0xFF));
        changePINAPDU.append(oldPINBytes);
        changePINAPDU.append(newPINBytes);
        changePINAPDU.append((byte)0x00);
        try{
            ResponseAPDU resp = myCS.sendCommandAPDU(changePINAPDU);
            System.out.println(changePINAPDU.toString()+resp.toString());

            short status = (short)resp.sw();
            switch(status){
            case SW_OK:
                return true;
            case SW_VERIFICATION_FAILED:
                return false;
            case SW_FALSE:
                throw new IllegalArgumentException("CLA not supporeted");
            case SW_INS_NOT_SUPPORTED:
                throw new IllegalArgumentException("INS not supported");
            default:
                throw new RuntimeException("Unknown Runtime Exception");
        }
        }catch(CardTerminalException e){
            throw new IOException("Connection fails");
        }catch(NullPointerException e){
            throw new IOException("Card service must been initialized first");
        }
    }

    public void credit(String amount)
    throws IllegalStateException,
    IllegalArgumentException,
    IOException{
        short amountShort = Short.parseShort(amount);
        byte[] amountBytes = new byte[2];
        amountBytes[1] = (byte)(amountShort & 0xFF);
        amountBytes[0] = (byte)(amountShort>>8);

        CommandAPDU setAccountNumberAPDU = new CommandAPDU(6+amountBytes.length);
        setAccountNumberAPDU.append(PURSE_CLA);
        setAccountNumberAPDU.append(CREDIT);
        setAccountNumberAPDU.append((byte)0x00);
        setAccountNumberAPDU.append((byte)0x00);
        setAccountNumberAPDU.append((byte)amountBytes.length);
        setAccountNumberAPDU.append(amountBytes);
        setAccountNumberAPDU.append((byte)0x00);
        String balanceStr;
        try{
            ResponseAPDU resp = myCS.sendCommandAPDU(setAccountNumberAPDU);
            System.out.println(setAccountNumberAPDU.toString()+resp.toString());

            short status = (short)resp.sw();
            switch(status){
            case SW_OK:
                return;
            case SW_NOT_VERIFIED:
                throw new IllegalStateException("User PIN not verified yet!");
            case SW_OVERFLOW:
                throw new IllegalArgumentException("Max account\'s balance is 1000");
            case SW_TRANSACTION_OVERFLOW:
                throw new IllegalArgumentException("Max transaction is 200");
            case SW_BAD_ARGUMENT:
                throw new IllegalArgumentException("Negative amount not allowed");
            case SW_FALSE:
                throw new IllegalArgumentException("CLA not supporeted");
            case SW_INS_NOT_SUPPORTED:
                throw new IllegalArgumentException("INS not supported");
            default:
                throw new RuntimeException("Unknown Runtime Exception");
            }
        }catch(CardTerminalException e){
            throw new IOException("Connection fails");
        }catch(NullPointerException e){
            throw new IOException("Card service must been initialized first");
        }
    }
    public void debit(String amount)
    throws IllegalStateException,
    IllegalArgumentException,
    IOException{
        short amountShort = Short.parseShort(amount);
        byte[] amountBytes = new byte[2];
        amountBytes[1] = (byte)(amountShort & 0xFF);
        amountBytes[0] = (byte)(amountShort>>8);

        CommandAPDU setAccountNumberAPDU = new CommandAPDU(6+amountBytes.length);
        setAccountNumberAPDU.append(PURSE_CLA);
        setAccountNumberAPDU.append(DEBIT);
        setAccountNumberAPDU.append((byte)0x00);
        setAccountNumberAPDU.append((byte)0x00);
        setAccountNumberAPDU.append((byte)amountBytes.length);
        setAccountNumberAPDU.append(amountBytes);
        setAccountNumberAPDU.append((byte)0x00);
        String balanceStr;
        try{
            ResponseAPDU resp = myCS.sendCommandAPDU(setAccountNumberAPDU);
            System.out.println(setAccountNumberAPDU.toString()+resp.toString());

            short status = (short)resp.sw();
            switch(status){
            case SW_OK:
                return;
            case SW_NOT_VERIFIED:
                throw new IllegalStateException("User PIN not verified yet!");
            case SW_UNDERFLOW:
                throw new IllegalArgumentException("Not enough funds in the account");
            case SW_TRANSACTION_OVERFLOW:
                throw new IllegalArgumentException("Max transaction is 200");
            case SW_BAD_ARGUMENT:
                throw new IllegalArgumentException("Negative amount not allowed");
            case SW_FALSE:
                throw new IllegalArgumentException("CLA not supporeted");
            case SW_INS_NOT_SUPPORTED:
                throw new IllegalArgumentException("INS not supported");
            default:
                throw new RuntimeException("Unknown Runtime Exception");
            }
        }catch(CardTerminalException e){
            throw new IOException("Connection fails");
        }catch(NullPointerException e){
            throw new IOException("Card service must been initialized first");
        }
    }


    public String getBalance()
    throws IllegalStateException,
    IOException,
    RuntimeException{
        CommandAPDU getBalanceAPDU = new CommandAPDU(7);
        getBalanceAPDU.setLength(0);
        getBalanceAPDU.append(PURSE_CLA);
        getBalanceAPDU.append(GET_BALANCE);
        getBalanceAPDU.append((byte)0x00);
        getBalanceAPDU.append((byte)0x00);
        getBalanceAPDU.append((byte)0x02);
        try{
            ResponseAPDU resp = myCS.sendCommandAPDU(getBalanceAPDU);
            System.out.println(getBalanceAPDU.toString()+resp.toString());
            short status = (short)resp.sw();
            switch(status){
            case SW_OK:
                byte[] data = resp.data();
                int balance;
                balance = (int) (data[1] & 0x0F);
                balance += (int) (data[1] & 0xF0);
                balance += (int) (data[0] << 8);
                return new String(Integer.toString(balance));
            case SW_NOT_VERIFIED:
                throw new IllegalStateException("User PIN not verified yet!");
            case SW_NO_DATA:
                return null;
            case SW_FALSE:
                throw new IllegalArgumentException("CLA not supporeted");
            case SW_INS_NOT_SUPPORTED:
                throw new IllegalArgumentException("INS not supported");
            case SW_WRONG_LE:
                throw new IllegalArgumentException("LE is wrong");
            default:
                throw new RuntimeException("Unknown Runtime Exception");
            }
        }catch(CardTerminalException e){
            e.printStackTrace();
            throw new IOException(/*"Connection fails"*/e.getMessage());
        }catch(NullPointerException e){
            e.printStackTrace();
            throw new IOException("Card service must been initialized first");
        }
    }

    public void setAccountNumber(String AccNo)
    throws IOException{
        byte[] AccBytes = AccNo.getBytes();

        CommandAPDU setAccountNumberAPDU = new CommandAPDU(6+AccBytes.length);
        setAccountNumberAPDU.append(PURSE_CLA);
        setAccountNumberAPDU.append(SET_ACCOUNT_NUMBER);
        setAccountNumberAPDU.append((byte)0x00);
        setAccountNumberAPDU.append((byte)0x00);
        setAccountNumberAPDU.append((byte)(AccBytes.length & 0xFF));
        setAccountNumberAPDU.append(AccBytes);
        setAccountNumberAPDU.append((byte)0x00);
        String balanceStr;
        try{
            ResponseAPDU resp = myCS.sendCommandAPDU(setAccountNumberAPDU);
            System.out.println(setAccountNumberAPDU.toString()+resp.toString());

            short status = (short)resp.sw();
            switch(status){
            case SW_OK:
                return;
            case SW_NOT_VERIFIED:
                throw new IllegalStateException("User PIN not verified yet!");
            case SW_BAD_ARGUMENT:
                throw new IllegalArgumentException("Account\'s number must have 5 elements");
            case SW_FALSE:
                throw new IllegalArgumentException("CLA not supporeted");
            case SW_INS_NOT_SUPPORTED:
                throw new IllegalArgumentException("INS not supported");
            default:
                throw new RuntimeException("Unknown Runtime Exception");
            }
        }catch(CardTerminalException e){
            throw new IOException("Connection fails");
        }catch(NullPointerException e){
            throw new IOException("Card service must been initialized first");
        }
    }

    public void setUserName(String UserName)
    throws IOException{
        byte[] UserNameBytes = UserName.getBytes();

        CommandAPDU setUserNameAPDU = new CommandAPDU(6+UserName.length());
        setUserNameAPDU.append(PURSE_CLA);
        setUserNameAPDU.append(SET_USER_NAME);
        setUserNameAPDU.append((byte)0x00);
        setUserNameAPDU.append((byte)0x00);
        setUserNameAPDU.append((byte)(UserName.length()& 0xFF));
        setUserNameAPDU.append(UserNameBytes);
        setUserNameAPDU.append((byte)0x00);
        try{
            ResponseAPDU resp = myCS.sendCommandAPDU(setUserNameAPDU);
            System.out.println(setUserNameAPDU.toString()+resp.toString());

            short status = (short)resp.sw();
            switch(status){
            case SW_OK:
                return;
            case SW_NOT_VERIFIED:
                throw new IllegalStateException("User PIN not verified yet!");
            case SW_BAD_ARGUMENT:
                throw new IllegalArgumentException("To long or empty string");
            case SW_FALSE:
                throw new IllegalArgumentException("CLA not supporeted");
            case SW_INS_NOT_SUPPORTED:
                throw new IllegalArgumentException("INS not supported");
            default:
                throw new RuntimeException("Unknown Runtime Exception");
            }
        }catch(CardTerminalException e){
            throw new IOException("Connection fails");
        }catch(NullPointerException e){
            throw new IOException("Card service must been initialized first");
        }
    }

    public void setUserSurname(String UserSurname)
    throws IOException{
        byte[] UserSurnameBytes = UserSurname.getBytes();

        CommandAPDU setUserNameAPDU = new CommandAPDU(6+UserSurname.length());
        setUserNameAPDU.append(PURSE_CLA);
        setUserNameAPDU.append(SET_USER_SURNAME);
        setUserNameAPDU.append((byte)0x00);
        setUserNameAPDU.append((byte)0x00);
        setUserNameAPDU.append((byte)(UserSurname.length()& 0xFF));
        setUserNameAPDU.append(UserSurnameBytes);
        setUserNameAPDU.append((byte)0x00);
        try{
            ResponseAPDU resp = myCS.sendCommandAPDU(setUserNameAPDU);
            System.out.println(setUserNameAPDU.toString()+resp.toString());

            short status = (short)resp.sw();
            switch(status){
            case SW_OK:
                return;
            case SW_NOT_VERIFIED:
                throw new IllegalStateException("User PIN not verified yet!");
            case SW_BAD_ARGUMENT:
                throw new IllegalArgumentException("To long or empty string");
            case SW_FALSE:
                throw new IllegalArgumentException("CLA not supporeted");
            case SW_INS_NOT_SUPPORTED:
                throw new IllegalArgumentException("INS not supported");
            default:
                throw new RuntimeException("Unknown Runtime Exception");
            }
        }catch(CardTerminalException e){
            throw new IOException("Connection fails");
        }catch(NullPointerException e){
            throw new IOException("Card service must been initialized first");
        }
    }

    public void setUserAddress(String UserAddress)
    throws IOException{
        byte[] UserSurnameBytes = UserAddress.getBytes();

        CommandAPDU setUserAddressAPDU = new CommandAPDU(6+UserAddress.length());
        setUserAddressAPDU.append(PURSE_CLA);
        setUserAddressAPDU.append(SET_USER_ADDRESS);
        setUserAddressAPDU.append((byte)0x00);
        setUserAddressAPDU.append((byte)0x00);
        setUserAddressAPDU.append((byte)(UserAddress.length()& 0xFF));
        setUserAddressAPDU.append(UserSurnameBytes);
        setUserAddressAPDU.append((byte)0x00);
        try{
            ResponseAPDU resp = myCS.sendCommandAPDU(setUserAddressAPDU);
            System.out.println(setUserAddressAPDU.toString()+resp.toString());

            short status = (short)resp.sw();
            switch(status){
            case SW_OK:
                return;
            case SW_NOT_VERIFIED:
                throw new IllegalStateException("User PIN not verified yet!");
            case SW_BAD_ARGUMENT:
                throw new IllegalArgumentException("To long or empty string");
            case SW_FALSE:
                throw new IllegalArgumentException("CLA not supporeted");
            case SW_INS_NOT_SUPPORTED:
                throw new IllegalArgumentException("INS not supported");
            default:
                throw new RuntimeException("Unknown Runtime Exception");
            }
        }catch(CardTerminalException e){
            throw new IOException("Connection fails");
        }catch(NullPointerException e){
            throw new IOException("Card service must been initialized first");
        }
    }

    public String getAccountNumber()
    throws IllegalStateException,
    IOException{
        CommandAPDU getUserAccountNoAPDU = new CommandAPDU(6);
        getUserAccountNoAPDU.append(PURSE_CLA);
        getUserAccountNoAPDU.append(GET_ACCOUNT_NUMBER);
        getUserAccountNoAPDU.append((byte)0x00);
        getUserAccountNoAPDU.append((byte)0x00);
        getUserAccountNoAPDU.append((byte)0x05);
        System.out.println(getUserAccountNoAPDU.toString());

        try{
            ResponseAPDU resp = myCS.sendCommandAPDU(getUserAccountNoAPDU);
            System.out.println(resp.toString());
            short status = (short)resp.sw();
            switch(status){
            case SW_OK:
                return new String(resp.data());
            case SW_NOT_VERIFIED:
                throw new IllegalStateException("User PIN not verified yet!");
            case SW_NO_DATA:
                return null;
            case SW_FALSE:
                throw new IllegalArgumentException("CLA not supporeted");
            case SW_INS_NOT_SUPPORTED:
                throw new IllegalArgumentException("INS not supported");
            default:
                throw new RuntimeException("Unknown Runtime Exception");
            }
        }catch(CardTerminalException e){
            e.printStackTrace();
            throw new IOException("Connection fails");
        }catch(NullPointerException e){
            throw new IOException("Card service must been initialized first");
        }
    }

    public String getUserName()
    throws IllegalStateException,
    IOException{
        CommandAPDU getUserNameAPDU = new CommandAPDU(6);
        getUserNameAPDU.append(PURSE_CLA);
        getUserNameAPDU.append(GET_USER_NAME);
        getUserNameAPDU.append((byte)0x00);
        getUserNameAPDU.append((byte)0x00);
        getUserNameAPDU.append((byte)0x0F);

        try{
            ResponseAPDU resp = myCS.sendCommandAPDU(getUserNameAPDU);
            System.out.println(getUserNameAPDU.toString()+resp.toString());
            short status = (short)resp.sw();
            switch(status){
            case SW_OK:
                return new String(resp.data());
            case SW_NOT_VERIFIED:
                throw new IllegalStateException("User PIN not verified yet!");
            case SW_NO_DATA:
                return null;
            case SW_FALSE:
                throw new IllegalArgumentException("CLA not supporeted");
            case SW_INS_NOT_SUPPORTED:
                throw new IllegalArgumentException("INS not supported");
            default:
                throw new RuntimeException("Unknown Runtime Exception");
            }
        }catch(CardTerminalException e){
            throw new IOException("Connection fails");
        }catch(NullPointerException e){
            throw new IOException("Card service must been initialized first");
        }
    }

    public String getUserSurname()
    throws IllegalStateException,
    IOException{
        CommandAPDU getUserSurameAPDU = new CommandAPDU(6);
        getUserSurameAPDU.append(PURSE_CLA);
        getUserSurameAPDU.append(GET_USER_SURNAME);
        getUserSurameAPDU.append((byte)0x00);
        getUserSurameAPDU.append((byte)0x00);
        getUserSurameAPDU.append((byte)0x0F);

        try{
            ResponseAPDU resp = myCS.sendCommandAPDU(getUserSurameAPDU);
            System.out.println(getUserSurameAPDU.toString()+resp.toString());
            short status = (short)resp.sw();
            switch(status){
            case SW_OK:
                return new String(resp.data());
            case SW_NOT_VERIFIED:
                throw new IllegalStateException("User PIN not verified yet!");
            case SW_NO_DATA:
                return null;
            case SW_FALSE:
                throw new IllegalArgumentException("CLA not supporeted");
            case SW_INS_NOT_SUPPORTED:
                throw new IllegalArgumentException("INS not supported");
            default:
                throw new RuntimeException("Unknown Runtime Exception");
            }
        }catch(CardTerminalException e){
            throw new IOException("Connection fails");
        }catch(NullPointerException e){
            throw new IOException("Card service must been initialized first");
        }
    }

    public String getUserAddress()
    throws IllegalStateException,
    IOException{
        CommandAPDU getUserAddressAPDU = new CommandAPDU(6);
        getUserAddressAPDU.append(PURSE_CLA);
        getUserAddressAPDU.append(GET_USER_ADDRESS);
        getUserAddressAPDU.append((byte)0x00);
        getUserAddressAPDU.append((byte)0x00);
        getUserAddressAPDU.append((byte)0x0F);

        try{
            ResponseAPDU resp = myCS.sendCommandAPDU(getUserAddressAPDU);
            System.out.println(getUserAddressAPDU.toString()+resp.toString());
            short status = (short)resp.sw();
            switch(status){
            case SW_OK:
                return new String(resp.data());
            case SW_NOT_VERIFIED:
                throw new IllegalStateException("User PIN not verified yet!");
            case SW_NO_DATA:
                return null;
            case SW_FALSE:
                throw new IllegalArgumentException("CLA not supporeted");
            case SW_INS_NOT_SUPPORTED:
                throw new IllegalArgumentException("INS not supported");
            default:
                throw new RuntimeException("Unknown Runtime Exception");
            }
        }catch(CardTerminalException e){
            throw new IOException("Connection fails");
        }catch(NullPointerException e){
            throw new IOException("Card service must been initialized first");
        }
    }

    private void jbInit() throws Exception {
    }
}
