/*
* Copyright 2011 Licel LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.licel.jcardsim.base;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javacard.framework.JCSystem;
import javacard.framework.SystemException;
/**
* Basic implementation of storage transient memory of JCRE.
*/
public class TransientMemory {
/** List of <code>CLEAR_ON_DESELECT</code> arrays */
protected final ArrayList<Object> clearOnDeselect = new ArrayList<Object>();
/** List of <code>CLEAR_ON_RESET</code> arrays */
protected final ArrayList<Object> clearOnReset = new ArrayList<Object>();
/**
* @see javacard.framework.JCSystem#makeTransientBooleanArray(short, byte)
* @param length the length of the array
* @param event the <code>CLEAR_ON...</code> event which causes the array elements to be cleared
* @return the new transient array
*/
public boolean[] makeBooleanArray(short length, byte event) {
boolean[] array = new boolean[length];
storeArray(array, event);
return array;
}
/**
* @see javacard.framework.JCSystem#makeTransientByteArray(short, byte)
* @param length the length of the array
* @param event the <code>CLEAR_ON...</code> event which causes the array elements to be cleared
* @return the new transient array
*/
public byte[] makeByteArray(int length, byte event) {
byte[] array = new byte[length];
storeArray(array, event);
return array;
}
/**
* @see javacard.framework.JCSystem#makeTransientShortArray(short, byte)
* @param length the length of the array
* @param event the <code>CLEAR_ON...</code> event which causes the array elements to be cleared
* @return the new transient array
*/
public short[] makeShortArray(short length, byte event) {
short[] array = new short[length];
storeArray(array, event);
return array;
}
/**
* @see javacard.framework.JCSystem#makeTransientObjectArray(short, byte)
* @param length the length of the array
* @param event the <code>CLEAR_ON...</code> event which causes the array elements to be cleared
* @return the new transient array
*/
public Object[] makeObjectArray(short length, byte event) {
Object[] array = new Object[length];
storeArray(array, event);
return array;
}
/**
* @see javacard.framework.JCSystem#isTransient(Object)
* @param theObj the object being queried
* @return <code>NOT_A_TRANSIENT_OBJECT</code>, <code>CLEAR_ON_RESET</code>, or <code>CLEAR_ON_DESELECT</code>
*/
public byte isTransient(Object theObj) {
if (clearOnDeselect.contains(theObj)) {
return JCSystem.CLEAR_ON_DESELECT;
} else if (clearOnReset.contains(theObj)) {
return JCSystem.CLEAR_ON_RESET;
}
return JCSystem.NOT_A_TRANSIENT_OBJECT;
}
/**
* Store <code>arrayRef</code> in memory depends by event type
* @param arrayRef array reference
* @param event event type
*/
protected void storeArray(Object arrayRef, byte event) {
switch (event) {
case JCSystem.CLEAR_ON_DESELECT:
clearOnDeselect.add(arrayRef);
break;
case JCSystem.CLEAR_ON_RESET:
clearOnReset.add(arrayRef);
break;
default:
SystemException.throwIt(SystemException.ILLEGAL_VALUE);
}
}
/**
* Zero <code>CLEAR_ON_DESELECT</code> buffers
*/
protected void clearOnDeselect() {
zero(clearOnDeselect);
}
/**
* Zero <code>CLEAR_ON_RESET</code> and <code>CLEAR_ON_DESELECT</code>
* buffers
*/
protected void clearOnReset() {
zero(clearOnDeselect);
zero(clearOnReset);
}
/**
* Perform <code>clearOnReset</code> and forget all buffers
*/
protected void forgetBuffers() {
clearOnReset();
clearOnDeselect.clear();
clearOnReset.clear();
}
/**
* Zero all arrays in list
* @param list list of arrays
*/
protected void zero(List<Object> list) {
for (Object obj : list) {
if (obj instanceof byte[]) {
Arrays.fill((byte[]) obj, (byte) 0);
}
else if (obj instanceof short[]) {
Arrays.fill((short[]) obj, (short) 0);
}
else if (obj instanceof Object[]) {
Arrays.fill((Object[])obj, null);
}
else if (obj instanceof boolean[]) {
boolean[] array = (boolean[]) obj;
for (int i = 0; i < array.length; ++i) {
array[i] = false;
}
}
}
}
}