FileDocCategorySizeDatePackage
JavaLoyalty.javaAPI DocJava Card5791Wed Mar 22 21:07:26 GMT 2006package com.sun.javacard.samples.JavaLoyalty

JavaLoyalty.java

/*
 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

/*
 * @(#)JavaLoyalty.java	1.13 06/01/03
 */

package	com.sun.javacard.samples.JavaLoyalty;

import javacard.framework.*;
import com.sun.javacard.samples.SampleLibrary.JavaLoyaltyInterface;

/**
 * Minimalistic loyalty applet.
 * JavaPurse uses grantPoints method implementing JavaLoyaltyInterface
 * to grant loyalty points. JavaLoyalty can process only two command APDUs:
 * READ_BALANCE and RESET_BALANCE.
 * @author Vadim Temkin
 */
public class JavaLoyalty extends Applet	implements JavaLoyaltyInterface  {
  
    /*
     *
     * Constants
     *
     */
    final static byte  READ_BALANCE  = (byte) 0x20;  //INS byte for Read Balance
    final static byte  RESET_BALANCE = (byte) 0x22;  //INS byte for Reset Balance
    final static byte  CREDIT        = (byte) 0x01;  //byte for Credit in grantPoints buffer
    final static byte  DEBIT		 = (byte) 0x02;	//byte for Debit in grantPoints buffer
    final static short TRANSACTION_TYPE_OFFSET = 2;
    final static short TRANSACTION_AMOUNT_OFFSET = 3;
    final static short SCALE         = (short) 100; //1 Loyalty Point per $1 (100c) debit
    final static short BALANCE_MAX   = (short)30000; //One won't get free flight from SFO to LAX
    //for this amount now, but we don't want to
    //introduce byte-array arithmetics for this
    //sample applet
    short balance;
  
    /**
     * Installs Java Loyalty applet.
     * @param bArray install parameter array.
     * @param bOffset where install data begins.
     * @param bLength install parameter data length.
     */
    public static void install( byte[] bArray, 
        short bOffset, byte bLength )  {
        new JavaLoyalty(bArray, bOffset, bLength);
    }
    
    /**
     * Performs memory allocations, initializations, and applet registration
     *
     * @param bArray received by install.
     * @param bOffset received by install.
     * @param bLength received by install.
     */
    protected JavaLoyalty(byte[] bArray,
        short bOffset, byte bLength) {
        balance = (short)0;
        /*
         * if AID length is not zero register Java Loyalty
         * applet with specified AID
         *
         * NOTE: all the memory allocations should be performed before register()
         */
    
        byte aidLen = bArray[bOffset];
        if (aidLen== (byte)0){
            register();
        } else {
            register(bArray, (short)(bOffset+1), aidLen);
        }
    }
  
    /**
     * Implements getShareableInterfaceObject method of Applet class.
     * <p>JavaLoyalty could check here if the clientAID is that of JavaPurse
     * Checking of the parameter to be agreed upon value provides additional
     * security, or, if the Shareable Interface Object weren't JavaLoyalty itself
     * it could return different Shareable Interface Objects for different values
     * of clientAID and/or parameter.
     * <p>See<em>Java Card Runtime Environment (JCRE) Specification</em> 
     * for details.
     *
     * @param clientAID AID of the client
     * @param parameter additional parameter
     * @return JavaLoyalty object
     */
    public Shareable getShareableInterfaceObject(AID clientAID,
        byte parameter) {
        if (parameter == (byte)0)
            return this;
        else 
            return null;
    }
    
    /**
     * Implements main interaction with a client. The data is transfered 
     * through APDU buffer  which is a global array accessible from any 
     * context. The format of data in the buffer is  subset of Transaction 
     * Log record format: 2 bytes of 0, 1 byte of transaction type, 2 bytes
     * amount of transaction, 4 bytes of CAD ID, 3 bytes of date, and 2 bytes 
     * of time. This sample implementation ignores everything but transaction
     * type and amount.
     * @param buffer APDU buffer
     */
    public void grantPoints (byte[] buffer) {
        short amount = Util.getShort(buffer, TRANSACTION_AMOUNT_OFFSET);
        amount = (short) (amount / SCALE);
        switch (buffer[TRANSACTION_TYPE_OFFSET]) {
        case DEBIT: 
            balance = (short)(balance + amount); break;
        case CREDIT: 
            balance = (short) (balance - amount); break;
        }
        if (balance < 0) balance = 0;
        if (balance > BALANCE_MAX) balance = BALANCE_MAX;
        /*
         * For this simple sample applet we don't keep track of transaction locations and
         * timestamps
         */
    }

    /**
     * Dispatches APDU commands.
     * @param apdu APDU
     */
    public void process(APDU apdu) {
        byte[] buffer = apdu.getBuffer();
        // We don't do any additional C-APDU header checking, just rely on
        // CLA and INS bytes for dispatching.
        
        if (apdu.isISOInterindustryCLA()) {
            if (buffer[ISO7816.OFFSET_INS] == (byte)(0xA4)) {
                return;
            } else {
                ISOException.throwIt (ISO7816.SW_CLA_NOT_SUPPORTED);
            }
        }
        
        switch (buffer[ISO7816.OFFSET_INS])	{
        case READ_BALANCE:  
            processReadBalance(apdu); break;
        case RESET_BALANCE: 
            processResetBalance(); break;
        default:
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }
  
    /**
     * Sends 2 bytes of balance value in R-APDU.
     * @param apdu APDU
     */
    void processReadBalance(APDU apdu) {
        byte[] buffer = apdu.getBuffer();
        Util.setShort(buffer, (short)0, balance);
        apdu.setOutgoingAndSend((short)0, (short)2);
    }
  
    /**
     * Resets Balance.
     */
    void processResetBalance()  {
        balance = (short)0;
    }
}