See: Description
Interface | Description |
---|---|
RecordComparator |
An interface defining a comparator which compares two records (in an
implementation-defined manner) to see if they match or what their relative
sort order is.
|
RecordEnumeration |
An interface representing a bidirectional record store Record enumerator.
|
RecordFilter |
An interface defining a filter which examines a record to see if it
matches (based on an application-defined criteria).
|
RecordListener |
A listener interface for receiving Record Changed/Added/Deleted events from a
record store.
|
Class | Description |
---|---|
RecordStore |
A class representing a record store.
|
RecordStoreInfo |
A class representing information about a RecordStore,
including authorization mode, encryption status, writeable status, and size
information.
|
Exception | Description |
---|---|
InvalidRecordIDException |
Thrown to indicate an operation could not be completed because the record ID
was invalid.
|
RecordStoreException |
Thrown to indicate a general exception occurred in a record store operation.
|
RecordStoreFullException |
Thrown to indicate an operation could not be completed because the record
store system storage is full.
|
RecordStoreNotFoundException |
Thrown to indicate an operation could not be completed because the record
store could not be found.
|
RecordStoreNotOpenException |
Thrown to indicate that an operation was attempted on a closed record store.
|
SecureRecordStoreException |
Thrown to indicate that a problem occurred during the process of Encrypting or
Decrypting data of a secure
RecordStore . |
RMS is modeled after a simple record-oriented database.
Unless otherwise noted, passing a null
argument to a constructor
or method in any class or interface in this package MUST cause a
NullPointerException
to be thrown.
Record stores are created in platform-dependent locations, which are not
exposed to applications. The naming space for record stores is controlled at
the application granularity. Applications are allowed to create multiple
record stores, as long as they are each given different names. When an
application is deleted from a platform, all record stores associated with it
MUST be deleted. The RecordStore API allows for the explicit sharing of
record stores if the application creating the RecordStore
chooses to give such permission.
MIDlet-Vendor
and
MIDlet-Name
attributes from the
application descriptor.
Record store names are case sensitive and MAY consist of any combination of between one and 32 Unicode characters inclusive. Record store names MUST be unique within the scope of a given application. In other words, applications are not allowed to create more than one record store with the same name; however, an application is allowed to have a record store with the same name as another application. In that case, the record stores are still distinct and separate.
Access controls are defined when record stores to be shared are created. Access controls are enforced when record stores are opened. An application suite defines access control by using access modes. The access modes allow private use or shareable with any other application suite.
Implementations MUST allow shared record stores to be opened concurrently by multiple applications. Successful updates to records MUST be visible to all applications when the update is complete. All RecordListeners to shared record stores must be notified after a record changes, regardless of the application that registered the listener and regardless of which application made the record update, both within and across applications.
RecordStore.setRecord()
concurrently on the same record, the record store will serialize these calls
properly, and no database corruption will occur as a result. However, one of
the writes will be subsequently overwritten by the other, which may cause
problems within the application. Similarly, if a platform performs transparent
synchronization of a record store or other access is the implementation's
responsibility to enforce exclusive access to the record store between the
applications and synchronization engine. The implementation MUST NOT
serialize calls to RecordListeners across execution environments. The
implementation MUST call the RecordListener callbacks in the order in which
additions, deletions, or changes took place on a record. Implementations MAY
coalesce record listener callbacks that resulted from multiple changes to a
particular record. Implementations MUST NOT discard any record listener
callbacks that resulted from record additions, deletions, or changes.
This record store API uses long integers for time/date stamps, in the format
used by System.currentTimeMillis()
. The record store is time
stamped with the last time it was modified. The record store also maintains a
version, which is an integer that is incremented for each operation that
modifies the contents of the record store. These are useful for
synchronization engines as well as applications.
RecordStore.openRecordStore
is overloaded to enable applications to open and
create different kinds of RecordStores. Some code examples are given below.
RecordStore rstore =
RecordStore.openRecordStore ( “MyRecordStore”, true);
// create one if not found
RecordStore rstore =
RecordStore.openRecordStore(“MyRecordStore”, false);
// open only an existing RecordStore.
int authmode = AUTHMODE_ANY;
boolean writable = true; // or false for read-only
RecordStore rstore =
RecordStore.openRecordStore(“MyRecordStore”, true,
AUTHMODE_ANY, writable);
String password = getPasswordFromUser ();
boolean writable = true; // or false for read-only
RecordStore rstore =
RecordStore.openRecordStore (“MyRecordStore”, true,
AUTHMODE_PRIVATE, writable, password);
String password = getPasswordFromUser ();
boolean writable = true; // or false for read-only
RecordStore rstore =
RecordStore.openRecordStore(“MyRecordStore”, true,
writable, password);
RecordStore rstore =
RecordStore.openRecordStore ( “OtherRecordStore”,
“OtherVendor”, “OtherApplication”);
String password = getPasswordFromUser ();
RecordStore rstore =
RecordStore.openRecordStore (“OtherRecordStore”,
“OtherVendor”,
“OtherApplication”,
password);
RecordComparator
and RecordFilter
are applied on
all the records of the record store. For a larger record store, finding a
particular record results in call backs on the RecordComparator
and RecordFilter
for all the records in the store, which is a
lot of overhead. The record tags provide an option to the developer to reduce
this overhead significantly.
Record tags allow developers to associate an integer tag with each record.
These tags are specified while calling
addRecord
or
setRecord
to the record
store. The developer can now specify these tags when calling enumeration, and
the implementation MUST only return those records for which the tags match.
As an example, if a record store has 100 records and the developer tags 10 records with the TAG value of 10. The developer can now call enumeration with tag value 10 and the implementation will only return those records with the tag value of 10. The developer has significantly reduced the number of records that need to be matched or compared.
When records are added with the legacy
addRecord
and
setRecord
API's, the
default value of tag MUST be 0.
Tags are not required to be encrypted by the implementation when a record store is locally encrypted. Since record tags may not be encrypted before being written to persistent storage, application developers should avoid storing sensitive information in clear text in record tags.
DataInputStream
and DataOutputStream
as well as
ByteArrayInputStream
and ByteArrayOutputStream
to
pack and unpack different data types into and out of the byte arrays.
Records are uniquely identified within a given record store by their
recordId
, which is an integer value. This recordId
is used as the primary key for the records. The first record created in a
record store will have recordId
equal to 1, and each subsequent
recordId
will monotonically increase by one. For example, if two
records are added to a record store, and the first has a recordId
of n
, the next will have a recordId
of
n+1
. Applications can create other indices by using the
RecordEnumeration. class.
import javax.microedition.rms.*; import javax.microedition.midlet.*; import javax.microedition.io.*; import java.io.*; import java.util.Vector; // An application for handling stock quotes. public class StockQuotes extends MIDlet implements RecordFilter, RecordComparator { // ... // The RecordStore used for storing the result values. private RecordStore recordStore = null; //The stock name to use when filtering. private String stockNameFilter = null;# // Part of the RecordFilter interface. public boolean matches(byte[] candidate) throws IllegalArgumentException { // If no filter set, nothing can match it. if (this.stockNameFilter == null) { return false; } ByteArrayInputStream bais = new ByteArrayInputStream(candidate); DataInputStream inputStream = new DataInputStream(bais); String name = null; try { int value = inputStream.readInt(); name = inputStream.readUTF(); } catch (EOFException eofe) { // ... } catch (IOException eofe) { // ... } return (this.stockNameFilter.equals(name)); } // Part of the RecordComparator interface. public int compare(byte[] rec1, byte[] rec2) { // Construct DataInputStreams for extracting the stock quotes from // the records. ByteArrayInputStream bais1 = new ByteArrayInputStream(rec1); DataInputStream inputStream1 = new DataInputStream(bais1); ByteArrayInputStream bais2 = new ByteArrayInputStream(rec2); DataInputStream inputStream2 = new DataInputStream(bais2); int quote1 = 0; int quote2 = 0; try { // Extract the stock quotes. quote1 = inputStream1.readInt(); quote2 = inputStream2.readInt(); } catch (EOFException eofe) { // ... } catch (IOException eofe) { // ... } // Sort by result value if (quote1 < quote2) { return RecordComparator.PRECEDES; } else if (quote1 > quote2) { return RecordComparator.FOLLOWS; } else { return RecordComparator.EQUIVALENT; } } public StockQuotes() { // constructor } // Start the Application. public void startApp() { // ... // Create the record store // try { recordStore = RecordStore.openRecordStore("mystocks", true); } catch (RecordStoreException rse) { // ... } // ... } public void destroyApp(boolean unconditional) { try { if(recordStore.getNumRecords() == 0) { String fileName = recordStore.getName(); recordStore.closeRecordStore(); recordStore.deleteRecordStore(fileName); } else { recordStore.closeRecordStore(); } } catch(RecordStoreNotOpenException e) { // ... } catch(RecordStoreException e) { // ... } notifyDestroyed(); } // Add a new stock to the record store. public void addStock() { // add to database // String input = ... String quoteString = getQuote(input); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream outputStream = new DataOutputStream(baos); try { outputStream.writeUTF(quoteString); } catch (IOException ioe) { // ... } byte[] b = baos.toByteArray(); try { recordStore.addRecord(b, 0, b.length); } catch (RecordStoreException rse) { // ... } // ... } // Get the quotes to be stored. // @param input stock name from input public String getQuote(String input) { // ... // (we won't tell you where we get the quotes from :-) } // List the stocks in the record store. public void listStocks() { stockList = new List( ... // ... try { // we don't use the filter here RecordEnumeration re = recordStore.enumerateRecords(null, this, false); while(re.hasNextElement()) { String stockValue = new String(re.nextRecord()); stockList.append( ... ); // stock name and value parsed from the record } } catch(RecordStoreNotOpenException e) { // ... } // ... (output somewhere) } // List the stocks in the record store for a particular stock name. public void listStocksFor(String stockName) { stockListForname = new List( ... ); // ... try { // this time we use the filter stockNameFilter = stockName; RecordEnumeration re = recordStore.enumerateRecords(this, this, false); // ... (rest of the method like listStocks() } } |
Copyright (c) 2014, Oracle and/or its affiliates. All Rights Reserved. Use of this specification is subject to license terms.