FileDocCategorySizeDatePackage
APDUManager.javaAPI DocphoneME MR2 API (J2ME)15776Wed May 02 18:00:38 BST 2007com.sun.midp.io.j2me.apdu

APDUManager

public class APDUManager extends Object
This class provides an interface to the low level APDU protocol details as described below: 1. Manage Card power up/reset. 2. APDU scheduler-Can assign priorities to APDUs to synchronize card access. Synchronization is required between APDUs being sent by native telecom software and APDUs sent by J2ME application. The reference implementation will only have APDUs sent by the J2ME application which would all have the same priority. 3. APDU Dispatcher-Support APDU exchange with the card. It has transaction capabilities to receive the APDUs from applications on the consumer device and return the responses to the corresponding application. 4. J2ME applications are oblivious of the logical channel information. Getting the logical channel for communicating with the smart card application is the responsibility of the APDUManager which sends appropriate APDUs to the card to get the logical channels assigned for a new connection or close channels when the connection is closed.

Fields Summary
private static final String
SAT_APDU_PROP
SAT selection APDU for testing purposes.
static Cad[]
cads
Contains references to all CADs or slots.
private static Object[]
sync
Objects used to synchronize access to CADs.
private static Handle
satHandle
Saved handle of open SAT connection.
Constructors Summary
Methods Summary
public static voidcheckSlotNumber(int slot)
Verifies that slot number is correct. Invokes init method if necessary.

param
slot the slot number
throws
ConnectionNotFoundException if slot number is wrong


        try {
            init();
        } catch (IOException e) {
            throw new ConnectionNotFoundException(
                "Invalid configuration");
        }
        if (slot < 0 || slot >= getSlotCount()) {
            throw new ConnectionNotFoundException(
                    "Invalid slot identifier: " + slot);
        }
    
public static voidcloseConnection(Handle h)
Closes the connection.

param
h connection handle
exception
IOException if there are any IO problems


        h.opened = false;
        synchronized (sync[h.slot]) {
            if (h.cardSessionId != h.getCardSessionId()) {
                throw new IOException();
            }
            h.cad.closeChannel(h.channel);
        }
    
public static byte[]exchangeAPDU(Handle h, byte[] apduData)
This method takes in the command APDU in the form of a byte array, converts it into an Apdu object which facilitates the processing of APDU data and then calls the exchangeAPDU method in CadClient to send the APDU to the card. If there are no errors, this method gets the response APDU data from the apdu object and returns that.

param
h connection handle
param
apduData APDU data in byte array form
return
response APDU data in byte array form
exception
IOException if there are any IO problems


        synchronized (sync[h.slot]) {

            if (cads[h.slot] == null) {
                try {
                    cads[h.slot] = new Cad(h.slot, h.token);
                } catch (IOException e) {
                    throw e;
                }
            }

            if (h.getCardSessionId() == -1) {
                throw new IOException("Card removed");
            }
            if (h.cardSessionId != h.getCardSessionId()) {
                throw new InterruptedIOException();
            }
            if (!h.opened) {
                throw new InterruptedIOException("Connection closed");
            }

            try {

                byte[] response = h.cad.exchangeApdu(h, apduData);

                if (!h.opened) {
                    throw new InterruptedIOException("Connection closed");
                }
                return response;
            } catch (InterruptedIOException ie) {
                throw ie;
            } catch (IOException e) {
                freeResources(h.slot);
                throw e;
            }
        }
    
private static voidfreeResources(int slotNumber)
Frees up connection resources if connection was closed because of an error.

param
slotNumber the selected slot

    	if (cads[slotNumber] != null) {
                cads[slotNumber].freeSystemResources(); 
    	}
    	cads[slotNumber] = null;
    
public static intgetSlotCount()
Returns the number of slots.

return
the number of slots. If error occured it returns 0.

        try {
            init();
        }
        catch (IOException e) {
            return 0;
        }
        return cads.length;
    
private static synchronized voidinit()
This method reads the configuration file for number of slots and their parameters and performs necessary initialization.

exception
IOException if there are any config problem


        if (cads != null) {
            return;
        }
        try {
            SlotFactory.init();
        }
        catch (CardDeviceException e) {
            throw new IOException("Config error: " + e.getMessage());
        }
        int slots = SlotFactory.getCardSlotCount();

        sync = new Object[slots];
        for (int i = 0; i < slots; i++) {
            sync[i] = new Object();
        }

        cads = new Cad[slots];
    
public static voidinitACL(int slot, com.sun.midp.security.SecurityToken securityToken)
Initializes ACL for the slot.

param
slot The slot number
param
securityToken Security token for this class

        try {
            init();
            synchronized (sync[slot]) {
                if (cads[slot] == null) {
                    cads[slot] = new Cad(slot, securityToken);
                }
                cads[slot].initACL();
            }
        } catch (IOException e) {} // ignored
    
public static booleanisSatSlot(int slot)
Checks if this slot is SAT slot.

param
slot the slot number
return
SAT check result
throws
IOException If an error occured.

        init();
        return SlotFactory.isSatSlot(slot);
    
public static HandleopenACLConnection(byte[] apdu, int slot, com.sun.midp.security.SecurityToken securityToken)
Opens a connection to a smart card for reading of ACL. This method is called from initACL method, so it does not need synchronized statement.

param
apdu The APDU that will be used for opening
param
slot Slot number
param
securityToken Security token for this class
return
new connection handle
exception
IOException when a card is not present or connection cannot be established with the card.

        
        Handle h = null;
        
        init();
        
        try {
            if (cads[slot] == null) {
                cads[slot] = new Cad(slot, securityToken);
            }
        } catch (IOException e) {
            freeResources(slot);
            throw new ConnectionNotFoundException("" + e);
        }
        try {
            return new Handle(slot,
                   cads[slot].selectApplication(true, apdu),
                   securityToken);
        } catch (IOException e) {
            if (cads[slot].isAlive()) {
                cads[slot].clean();
                throw e;
            }
            // at this point we need to close slot
            freeResources(slot);
            throw e;
        }
    
static HandleopenSATConnection(int slot, com.sun.midp.security.SecurityToken securityToken)
This method is called when there is SAT connection creation in progress. This method checks if the the required CAD objects have been created or not and creates them. It then checks if the SIM application has been selected and can be communicated with. If it is not present, this method throws ConnectionNotFound exception. If SAT connection is in use this method throws IOException.

param
slot Slot number
param
securityToken Security token for this class
return
new connection handle
exception
IOException when SIM is not present or connection cannot be established with the card.

    
                                                                                                        
         
          
        
        Handle h = null;
        
        init();
        
        /*
         * IMPL_NOTE: SATSA spec does not require checking for existence.
         * JDTS test does not close old connection and tries open new one.
         */
if (false) { 
        // Check if old SAT connection still alive
        if (satHandle != null &&
                satHandle.opened &&
                satHandle.cad.getCardSessionId() != -1 &&
                satHandle.cardSessionId == satHandle.cad.getCardSessionId()) {
            throw new IOException("SAT already open");
        }
}
        synchronized (sync[slot]) {
            try {
                if (cads[slot] == null) {
                    cads[slot] = new Cad(slot, securityToken);
                }
            } catch (IOException e) {
                freeResources(slot);
                throw new ConnectionNotFoundException("" + e);
            }
            String satAPDU = Configuration.getProperty(SAT_APDU_PROP);
            if (satAPDU != null) {
                byte[] apdu = new byte[24];
                boolean ok;
                try {
                    int len = parseDottedBytes(satAPDU, apdu, 0);
                    ok = len >= 10 && len <= 22; // 5 bytes hdr + AID + Le
                    int Lc = (apdu[4] & 0xFF);
                    if (ok && (len < Lc + 5 || 
                               len > Lc + 5 + 1 ||
                               apdu[0] != (byte)0x00 ||
                               apdu[1] != (byte)0xA4 ||
                               apdu[2] != (byte)0x04)) {
                        ok = false;
                    }
                    if (ok && len == Lc + 5) {
                        apdu[len] = 0x7F;
                    }
                } catch (NullPointerException npe) {
                    ok = false;
                } catch (IndexOutOfBoundsException iobe) {
                    ok = false;
                } catch (IllegalArgumentException iae) {
                    ok = false;
                }
    
                if (ok) {
                    try {
                        h = new Handle(slot,
                            cads[slot].selectApplication(true, apdu),
                            securityToken);
                    } catch (IOException e) {
                        if (cads[slot].isAlive()) {
                            cads[slot].clean();
                            throw e;
                        }
                        // at this point we need to close socket
                        freeResources(slot);
                        throw e;
                    }
                }
            }
            if (h == null) {
                if (!cads[slot].isAlive()) {
                    throw new ConnectionNotFoundException("SIM not found");
                }
                h = new Handle(slot, 0, securityToken);
            }
            satHandle = h; // Save handle created for SAT connection
            return h;
        }
    
public static intparseDottedBytes(java.lang.String src, byte[] dest, int offset)
Parses string that contains hexadecimal byte values separated by dots. May throw runtime exceptions.

param
src source string
param
dest destination array
param
offset target offset
return
number of bytes parsed


        int i = 0;
        int len = 0;
        int j;

        while (i != src.length() + 1) {

            if ((j = src.indexOf('.", i)) == -1) {
                j = src.length();
            }

            int l = Integer.parseInt(src.substring(i, j), 16);
            if (l != (l & 0xff)) {
                throw new IllegalArgumentException();
            }
            dest[offset + len++] = (byte) l;
            i = j + 1;
        }
        return len;
    
public static HandleselectApplication(byte[] selectAPDU, int slot, com.sun.midp.security.SecurityToken securityToken)
This method is called when there is a connection creation is in progress and specifically card application selection is required. This method checks if the the required CAD objects have been created or not and creates them. It then calls the selectApplication method on the CAD to select the application. If the card application selection is successful this method gets the channel information from the CAD which it returns to the APDUConnection object.

param
selectAPDU byte encoded selection APDU
param
slot contains the information regarding the slot the has the card containing the application with which connection needs to be established
param
securityToken Security token for this class
return
new connection handle
exception
IOException when selection is not successful


        init();
        synchronized (sync[slot]) {
            try {
                if (cads[slot] == null) {
                    cads[slot] = new Cad(slot, securityToken);
                }
            } catch (IOException e) {
                freeResources(slot);
                throw new ConnectionNotFoundException("" + e);
            }
            try {
                return new Handle(slot,
                        cads[slot].selectApplication(false, selectAPDU),
                        securityToken);
            } catch (IOException e) {
                if (cads[slot].isAlive()) {
                    cads[slot].clean();
                    throw e;
                }
                // at this point we need to close slot
                freeResources(slot);
                throw e;
            }
        }