问题
Consider a Java Card Classic applet with multiple instances that need to share some data in a byte[] variable (e.g. persistent mutable, that is EEPROM/Flash), containing information common to all instances.
A static byte[] variable would be a perfect fit, but these happen to be prohibited by validation rules imposed on me (I'm told: as a catch-all way to demonstrate that un-instantiating an instance frees what it allocated on instantiation).
This would be solved if a slave instance could call one of the applet's method in the context of a master instance (perhaps initially identified by AID, or/and/then in some other way). How can this be done? Any example?
Update: the code in this other question is next to doing what I want shares objects, but does not seem to call a method in the context of another instance.
回答1:
A tested example, as promised:
package nl.owlstead.javacard.sharedarray;
import javacard.framework.*;
/**
* The master and slave AID should only differ in the last byte; the master should end with the 'm' ASCII character.
* This applet is for demonstration purposes only.
*
* @author owlstead@stackoverflow
*/
public class SharingApplet extends Applet {
public interface SharedArray extends Shareable {
public byte[] getSharedArray();
}
public static class SharedArrayImpl implements SharedArray {
private byte[] sharedArray;
public SharedArrayImpl(final byte[] arrayToShare) {
this.sharedArray = arrayToShare;
}
public byte[] getSharedArray() {
return sharedArray;
}
}
private static final short MAX_AID_SIZE = 16;
private static final short START = 0;
private static final byte SHARABLE_PARAM = 0;
private static final byte PARAM_SHARED_ARRAY = 0;
public static void install(byte[] bArray, short bOffset, byte bLength) {
final byte aidLength = bArray[bOffset++];
final byte lastAIDByte = bArray[(short) (bOffset + aidLength - 1)];
final boolean isMaster = lastAIDByte == 'm';
final SharingApplet applet = new SharingApplet(isMaster);
applet.register(bArray, bOffset, aidLength);
applet.setMasterAID();
}
// if null, it is not the master
private final SharedArray sharedArray;
private AID masterAID;
public SharingApplet(final boolean isMaster) {
if (isMaster) {
final byte[] sa = new byte[] { 'm' };
sharedArray = new SharedArrayImpl(sa);
} else {
sharedArray = null;
}
}
public void process(APDU apdu) {
if (selectingApplet()) {
return;
}
byte[] buf = apdu.getBuffer();
switch (buf[ISO7816.OFFSET_INS]) {
case (byte) 0x00: {
final SharedArray theSharedArray;
if (sharedArray == null) {
theSharedArray = (SharedArray) JCSystem.getAppletShareableInterfaceObject(masterAID, SHARABLE_PARAM);
} else {
theSharedArray = sharedArray;
}
final byte[] sa = theSharedArray.getSharedArray();
Util.arrayCopy(sa, START, buf, START, (short) sa.length);
apdu.setOutgoingAndSend(START, (short) sa.length);
break;
}
case (byte) 0x02: {
final SharedArray theSharedArray;
if (sharedArray == null) {
theSharedArray = (SharedArray) JCSystem.getAppletShareableInterfaceObject(masterAID, SHARABLE_PARAM);
final byte[] sa = theSharedArray.getSharedArray();
sa[START] = 's';
} else {
theSharedArray = sharedArray;
final byte[] sa = theSharedArray.getSharedArray();
sa[START] = 'm';
}
break;
}
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
}
private void setMasterAID() {
final byte[] workspace = new byte[MAX_AID_SIZE];
final AID slaveOrMasterAID = JCSystem.getAID();
final byte aidLength = slaveOrMasterAID.getBytes(workspace, START);
workspace[(short) (aidLength - 1)] = 'm';
this.masterAID = new AID(workspace, START, aidLength);
}
public Shareable getShareableInterfaceObject(AID clientAID, byte parameter) {
if (sharedArray == null || parameter != PARAM_SHARED_ARRAY) {
return null;
}
return sharedArray;
}
}
来源:https://stackoverflow.com/questions/14238849/javacard-how-can-an-applets-instance-call-a-method-in-another-instances-conte