Methods Summary |
---|
public javax.microedition.payment.TransactionRecord | addTransaction(com.sun.j2me.payment.Transaction transaction)Adds the given transaction to the store. It returns a new transaction
record for the transaction. This transaction record must have its
wasMissed flag cleared.
int transactionID = transaction.getTransactionID();
CldcTransactionRecordImpl record = findReservedRecord(transactionID);
if (record == null) {
throw new IllegalStateException("The transaction record hasn't " +
"been reserved");
}
record.setStatus(CldcTransactionRecordImpl.MISSED);
record.update(transaction);
if (!record.isFake()) {
try {
TransactionStorageImpl store =
new TransactionStorageImpl(securityToken, false);
try {
writeTransactionRecord(record, store, record.getRecordID());
} finally {
store.closeStore();
}
} catch (RecordStoreException ex) {
throw new IOException("Storage Failure: " + ex.getMessage());
}
}
// store the transaction record as missed but return it as not missed
return record.createDuplicateRecord();
|
public void | cleanUp()Removes all transaction records from the store. This is a helper method
which is used in test suites to get clean state before test execution.
try {
TransactionStorageImpl.deleteStore(securityToken);
} catch (RecordStoreException ex) {
// Nothing to do
}
initStore();
|
private CldcTransactionRecordImpl | findMissedRecord(int transactionID)Finds missed Transaction Record with the given Transaction ID
return findRecord(transactionID, CldcTransactionRecordImpl.MISSED);
|
private CldcTransactionRecordImpl | findRecord(int transactionID, int status)Finds Transaction Record with given Transaction ID and status
CldcTransactionRecordImpl r = null;
CldcTransactionRecordImpl record = null;
synchronized (tsLock) {
int count = inProcessRecords.size();
/* Try to find in the vector */
for (int i = 0; i < count; ++i) {
r = (CldcTransactionRecordImpl)
inProcessRecords.elementAt(i);
if (r.getTransactionID() == transactionID) {
return r;
}
}
}
/* Get none-fake elements */
try {
TransactionStorageImpl store =
new TransactionStorageImpl(securityToken, false);
try {
/* fiind reserved transaction */
int[] recordIDs = store.getRecordIDs();
for (int i = 0; i < recordIDs.length; i++) {
int recId = recordIDs[i];
r = readTransactionRecord(store, recId);
if (null != r &&
(r.getTransactionID() == transactionID) &&
(r.getStatus() == status)) {
r.setRecordID(recId);
record = r;
break;
}
}
} finally {
store.closeStore();
}
} catch (RecordStoreException ex) {
throw new IOException("Storage Failure: " + ex.getMessage());
} catch (IOException ex) {
throw new IOException("Storage Failure: " + ex.getMessage());
}
return record;
|
private CldcTransactionRecordImpl | findReservedRecord(int transactionID)Finds reserved Transaction Record with the given Transaction ID
return findRecord(transactionID, CldcTransactionRecordImpl.RESERVED);
|
void | generateFakeRecords(int applicationID, java.lang.String applicationName, com.sun.j2me.payment.PaymentInfo paymentInfo, java.lang.String featurePrefix, int[] validProviders, int count)Generates Fake records for Debug mode
// count > 0
// reserve transaction IDs
int transactionID;
try {
TransactionStorageImpl store =
new TransactionStorageImpl(securityToken, false);
try {
/* assign transactionID */
int nextTransactionID = getIntFromByteArray(
store.getRecord(NEXT_TRANSACTION_RECORD_ID));
transactionID = nextTransactionID;
nextTransactionID += count;
if (nextTransactionID <= 0) {
nextTransactionID = count;
}
store.setRecord(NEXT_TRANSACTION_RECORD_ID,
getByteArrayFromInt(nextTransactionID));
} finally {
store.closeStore();
}
} catch (RecordStoreException ex) {
throw new IOException("Storage Failure: " + ex.getMessage());
}
Random random = new Random();
long timestamp = System.currentTimeMillis() - 3600000;
int deltaTime = 3600000 / count;
int numFeatures = paymentInfo.getNumFeatures();
for (int i = 0; i < count; ++i) {
int state = random.nextInt(3);
int featureID = (i + (count >>> 1)) * (numFeatures - 1) / count;
double price;
String currency;
if (state != TransactionRecord.TRANSACTION_REJECTED) {
int priceTag = paymentInfo.getPriceTagForFeature(featureID);
int providerID = validProviders[
random.nextInt(validProviders.length)];
ProviderInfo providerInfo = paymentInfo.getProvider(providerID);
price = providerInfo.getPrice(priceTag);
currency = providerInfo.getCurrency();
} else {
price = 0;
currency = "";
}
inProcessRecords.addElement(
CldcTransactionRecordImpl.createFakeRecord(
transactionID++, applicationID, applicationName,
featureID, featurePrefix + featureID, price, currency,
state, timestamp));
if (transactionID <= 0) {
transactionID = 1;
}
timestamp += deltaTime;
}
|
static byte[] | getByteArrayFromInt(int v)puts integer into the ByteArray
byte[] data = new byte[SIZE_OF_INT];
data[0] = (byte) ((byte) ((v) >> 24) & 0xFF);
data[1] = (byte) ((byte) ((v) >> 16) & 0xFF);
data[2] = (byte) ((byte) ((v) >> 8) & 0xFF);
data[3] = (byte) ((byte) (v) & 0xFF);
return data;
|
static int | getIntFromByteArray(byte[] data)retrives Int from the ByteArray
if (data.length == SIZE_OF_INT) {
return (((int) (data[0]) << 24) |
((int) (data[1]) << 16) |
((int) (data[2]) << 8) |
(int) (data[3]));
}
return -1;
|
javax.microedition.payment.TransactionRecord[] | getMissedTransactions(int applicationID, boolean fakeOnly)Returns an array of the missed transaction records for the given
application ID. The transaction records are returned in the order in
which they have been added to the store. Each transaction record must
have its wasMissed flag set.
Vector missedRecords = new Vector();
if (!fakeOnly) {
missedRecords = getTransactions(applicationID, true);
}
synchronized (tsLock) {
/* Get FakeOnly elements */
for (int i = 0; i < inProcessRecords.size(); ++i) {
CldcTransactionRecordImpl record =
(CldcTransactionRecordImpl)inProcessRecords.elementAt(i);
if ((record.getApplicationID() == applicationID) &&
record.wasMissed() && record.isFake()) {
record.add2list(missedRecords);
}
}
}
int count = missedRecords.size();
if (count == 0) {
return null;
}
CldcTransactionRecordImpl[] appRecords =
new CldcTransactionRecordImpl[count];
missedRecords.copyInto(appRecords);
return appRecords;
|
public javax.microedition.payment.TransactionRecord[] | getMissedTransactions(int applicationID)Returns an array of the missed transaction records for the given
application ID. The transaction records are returned in the order in
which they have been added to the store. Each transaction record must
have its wasMissed flag set.
return getMissedTransactions(applicationID, false);
|
public int | getNextApplicationID()Returns an identification number, which can be used as
applicationID in the other methods. During installation
each payment supporting MIDletSuite should get such number
and have it stored. From that point this number will identify that
MIDletSuite to the transaction store.
int nextApplicationID = 0;
try {
TransactionStorageImpl store =
new TransactionStorageImpl(securityToken, false);
try {
nextApplicationID = getIntFromByteArray(
store.getRecord(NEXT_APPLICATION_RECORD_ID));
nextApplicationID++;
if (nextApplicationID <= 0) {
nextApplicationID = 1;
}
store.setRecord(NEXT_APPLICATION_RECORD_ID,
getByteArrayFromInt(nextApplicationID));
} finally {
store.closeStore();
}
} catch (RecordStoreException ex) {
throw new IOException("Storage Failure");
}
return nextApplicationID;
|
public javax.microedition.payment.TransactionRecord[] | getPassedTransactions(int applicationID)Returns an array of the past transaction records for the given
application ID. The transaction record are returned in the reverse order
as they have been added to the store (most recent first). Each
transaction record must have its wasMissed flag cleared.
Vector passedRecords = getTransactions(applicationID, false);
int count = passedRecords.size();
if (count == 0) {
return null;
}
CldcTransactionRecordImpl[] appRecords =
new CldcTransactionRecordImpl[count];
/* sort passedRecords and store in appRecords (reverse mode) */
for (int i = 0, j = (count - 1); i < count; i++, j--) {
appRecords[j] = (CldcTransactionRecordImpl)
passedRecords.elementAt(i);
}
passedRecords.removeAllElements();
return appRecords;
|
public int | getSizeUsedByApplication(int applicationID)Returns the size which is used in the store by the application of the
given application ID. This size doesn't include the size of the passed
transactions (it includes only the part of the store which is
removed/uninstalled by the removeApplicationRecords method).
int size = 0;
try {
TransactionStorageImpl store =
new TransactionStorageImpl(securityToken, false);
try {
/* read missed transactions */
int[] recordIDs = store.getRecordIDs();
CldcTransactionRecordImpl r;
for (int i = 0; i < recordIDs.length; i++) {
int recId = recordIDs[i];
r = readTransactionRecord(store, recId);
if (null != r &&
(r.getApplicationID() == applicationID) &&
r.wasMissed()) {
size += store.getRecordSize(recId);
}
}
} finally {
store.closeStore();
}
}
catch (RecordStoreException ex) {
throw new IOException("Storage Failure: " + ex.getMessage());
}
return size;
|
private java.util.Vector | getTransactions(int applicationID, boolean wasMissed)Returns a Vector of passed or missed transaction records for the given
application ID.
Vector records = new Vector();
/* Get none-fake elements */
try {
TransactionStorageImpl store =
new TransactionStorageImpl(securityToken, false);
try {
/* read passed transactions */
int[] recordIDs = store.getRecordIDs();
CldcTransactionRecordImpl r;
for (int i = 0; i < recordIDs.length; i++) {
int recId = recordIDs[i];
r = readTransactionRecord(store, recId);
if (null != r &&
(r.getApplicationID() == applicationID) &&
(r.wasMissed() == wasMissed)) {
r.add2list(records);
}
}
} finally {
store.closeStore();
}
} catch (RecordStoreException ex) {
throw new IOException("Storage Failure: " + ex.getMessage());
}
return records;
|
private void | initStore()Initializes the store. It's used when the transaction store file doesn't
exists.
int nextTransactionID = 1;
int nextApplicationID = 1;
try {
TransactionStorageImpl store =
new TransactionStorageImpl(securityToken, true);
try {
if (store.getNumRecords() == 0) {
/* Record ID = NEXT_TRANSACTION_RECORD_ID */
store.addRecord(getByteArrayFromInt(nextTransactionID));
/* Record ID = NEXT_APPLICATION_RECORD_ID */
store.addRecord(getByteArrayFromInt(nextApplicationID));
}
} catch (RecordStoreException ex) {
throw new IOException(
"Error initializing Transaction Store: " + ex.getMessage());
} finally {
store.closeStore();
}
} catch (RecordStoreFullException ex) {
throw new IOException("Error initializing Transaction Store: " +
ex.getMessage());
} catch (RecordStoreException ex) {
/* Nothing to do. The store is creating by another isolate */
}
|
private void | limitPassedRecords(TransactionStorageImpl st)Limits the count of the passed transaction records in the given
vector to the given value.
Vector passedRecords = new Vector();
CldcTransactionRecordImpl r;
/* read passed transactions */
int[] recordIDs = st.getRecordIDs();
for (int i = 0; i < recordIDs.length; i++) {
int recId = recordIDs[i];
r = readTransactionRecord(st, recId);
if (null != r &&
!r.wasMissed()) {
r.add2list(passedRecords);
}
}
while (passedRecords.size() > PASSED_TRANSACTIONS_LIMIT) {
r = (CldcTransactionRecordImpl) passedRecords.elementAt(0);
st.deleteRecord(r.getRecordID());
passedRecords.removeElementAt(0);
}
|
private CldcTransactionRecordImpl | readTransactionRecord(TransactionStorageImpl st, int recId)This service function reads and returns TransactionRecord from store.
byte[] nextRec = st.getRecord(recId);
CldcTransactionRecordImpl r = null;
if (nextRec.length > SIZE_OF_INT) {
ByteArrayInputStream bis =
new ByteArrayInputStream(nextRec);
DataInputStream is = new DataInputStream(bis);
r = CldcTransactionRecordImpl.read(is);
r.setRecordID(recId);
}
return r;
|
public void | removeApplicationRecords(int applicationID)Removes the missed records used by the application of the given
application ID. This is to be used, when the MIDlet suite is uninstalled.
try {
TransactionStorageImpl store =
new TransactionStorageImpl(securityToken, false);
try {
/* read missed and passed transactions */
int[] recordIDs = store.getRecordIDs();
CldcTransactionRecordImpl r;
for (int i = 0; i < recordIDs.length; i++) {
int recId = recordIDs[i];
r = readTransactionRecord(store, recId);
if (null != r &&
(r.getApplicationID() == applicationID) &&
r.wasMissed()) {
store.deleteRecord(recId);
}
}
} finally {
store.closeStore();
}
} catch (RecordStoreException ex) {
throw new IOException("Storage Failure: " + ex.getMessage());
}
synchronized (tsLock) {
/* count missed and reserved transactions */
CldcTransactionRecordImpl r;
for (int i = (inProcessRecords.size() - 1); i >= 0; i--) {
r = (CldcTransactionRecordImpl)
inProcessRecords.elementAt(i);
if (r.wasMissed() &&
(r.getApplicationID() == applicationID)) {
inProcessRecords.removeElementAt(i);
}
}
}
|
protected void | removeMissedTransaction(int appID)Remove missed transaction for give application.
CldcTransactionRecordImpl[] recs =
(CldcTransactionRecordImpl[]) getMissedTransactions(appID);
if (null == recs) {
return;
}
try {
TransactionStorageImpl store =
new TransactionStorageImpl(securityToken, false);
try {
for (int i = 0; i < recs.length; i++) {
store.deleteRecord(recs[i].getRecordID());
}
} finally {
store.closeStore();
}
} catch (RecordStoreException ex) {
throw new IOException("Storage Failure: " + ex.getMessage());
}
|
public int | reserve(int applicationID, com.sun.j2me.payment.Transaction transaction)Reserves space for the given transaction in the store. It should be
called before any call to the addTransaction method to
ensure that the addTransaction method won't fail later
(when it is inappropriate) due to full store. This method can apply some
store policies, like enforcing a maximum number of missed transactions
per MIDletSuite .
The applicationID identifies the application (MIDlet suite)
to the transaction store. MIDlet suites which are run directly can use
negative application IDs to avoid permanent storing of created
transaction records.
/* assign transactionID */
int transactionID;
try {
TransactionStorageImpl store =
new TransactionStorageImpl(securityToken, false);
try {
int count = 0;
/* count missed and reserved transactions */
CldcTransactionRecordImpl r;
for (int i = 0; i < inProcessRecords.size(); i++) {
r = (CldcTransactionRecordImpl)
inProcessRecords.elementAt(i);
if (r.wasMissed() &&
(r.getApplicationID() == applicationID)) {
count++;
}
}
/* check the limit */
if (count >= MISSED_TRANSACTIONS_LIMIT) {
throw new IOException("No more space for records");
}
String applicationName = transaction.
getTransactionModule().getMIDlet().
getAppProperty(MIDletSuiteImpl.SUITE_NAME_PROP);
/* assign transactionID */
int nextTransactionID = getIntFromByteArray(
store.getRecord(NEXT_TRANSACTION_RECORD_ID));
transactionID = nextTransactionID++;
if (nextTransactionID <= 0) {
nextTransactionID = 1;
}
transaction.setTransactionID(transactionID);
/* don't reserve space if applicationID < 0 */
if (applicationID > 0) {
/* create reserved transaction */
CldcTransactionRecordImpl newTransactionRecord =
new CldcTransactionRecordImpl(
applicationID, applicationName,
transaction, System.currentTimeMillis(),
false);
store.setRecord(NEXT_TRANSACTION_RECORD_ID,
getByteArrayFromInt(nextTransactionID));
writeTransactionRecord(newTransactionRecord, store, 0);
inProcessRecords.addElement(newTransactionRecord);
} else {
/* create reserved fake transaction */
CldcTransactionRecordImpl newTransactionRecord =
new CldcTransactionRecordImpl(
applicationID, applicationName,
transaction, System.currentTimeMillis(),
true);
inProcessRecords.addElement(newTransactionRecord);
}
} finally {
store.closeStore();
}
} catch (RecordStoreException ex) {
throw new IOException("Storage Failure: " +
ex.getMessage());
}
return transactionID;
|
public void | setDelivered(int transactionID)This method is called after the application is successfully notified
about the transaction with the given transaction ID.
CldcTransactionRecordImpl transactionRecord = null;
synchronized (tsLock) {
transactionRecord = findMissedRecord(transactionID);
if (transactionRecord == null) {
throw new IllegalArgumentException("Not a stored transaction");
}
inProcessRecords.removeElement(transactionRecord);
}
if (!transactionRecord.isFake()) {
transactionRecord.setStatus(CldcTransactionRecordImpl.PASSED);
try {
TransactionStorageImpl store =
new TransactionStorageImpl(securityToken, false);
try {
if (transactionRecord.getRecordID() > 0) {
writeTransactionRecord(transactionRecord,
store, transactionRecord.getRecordID());
}
// limit the passed transactions count
limitPassedRecords(store);
} finally {
store.closeStore();
}
} catch (RecordStoreException ex) {
throw new IOException("Storage Failure " + ex.getMessage());
}
}
|
public boolean | wasDelivered(int transactionID)It returns true if the setDelivered method
was called for the given transaction ID.
CldcTransactionRecordImpl transactionRecord = findMissedRecord(
transactionID);
return transactionRecord == null;
|
private void | writeTransactionRecord(CldcTransactionRecordImpl record, TransactionStorageImpl st, int recId)This service function writes TransactionRecord into store.
/* formate transaction inside ByteArray */
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream os = new DataOutputStream(bos);
record.write(os);
byte[] data = bos.toByteArray();
if (recId == 0) {
recId = st.addRecord(data);
record.setRecordID(recId);
} else {
st.setRecord(recId, data);
}
|