001: /*
002: *
003: *
004: * Portions Copyright 2000-2007 Sun Microsystems, Inc. All Rights
005: * Reserved. Use is subject to license terms.
006: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
007: *
008: * This program is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU General Public License version
010: * 2 only, as published by the Free Software Foundation.
011: *
012: * This program is distributed in the hope that it will be useful, but
013: * WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * General Public License version 2 for more details (a copy is
016: * included at /legal/license.txt).
017: *
018: * You should have received a copy of the GNU General Public License
019: * version 2 along with this work; if not, write to the Free Software
020: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
021: * 02110-1301 USA
022: *
023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
024: * Clara, CA 95054 or visit www.sun.com if you need additional
025: * information or have any questions.
026: *
027: * Copyright 2000 Motorola, Inc. All Rights Reserved.
028: * This notice does not imply publication.
029: */
030:
031: package com.sun.midp.rms;
032:
033: import java.io.IOException;
034:
035: import javax.microedition.rms.InvalidRecordIDException;
036: import javax.microedition.rms.RecordStoreException;
037: import javax.microedition.rms.RecordStoreFullException;
038: import javax.microedition.rms.RecordStoreNotOpenException;
039:
040: /**
041: * An interface for a record store implementation.
042: */
043:
044: interface AbstractRecordStoreImpl {
045: /*
046: * The layout of the database file is as follows:
047: *
048: * Bytes - Usage
049: * 00-07 - Signature = 'midp-rms'
050: * 08-11 - Authmode and Writable state info
051: * 12-15 - Next record ID to use (big endian)
052: * 16-19 - Number of live records in the database (big endian)
053: * 20-23 - Database "version" - a monotonically increasing revision
054: * number (big endian)
055: * 24-31 - Last modified (64-bit long, big endian, milliseconds since
056: * jan 1970)
057: * 32-35 - Size of Data storage (big endian)
058: * 36-39 - Size of Free storage (big endian)
059: * 40-xx - Record storage
060: */
061:
062: /** RS_SIGNATURE offset */
063: static final int RS0_SIGNATURE = 0;
064:
065: /** RS_AUTHMODE offset */
066: static final int RS1_AUTHMODE = 8;
067:
068: /** RS_NEXT_ID offset */
069: static final int RS2_NEXT_ID = 12;
070:
071: /** RS_NUM_LIVE offset */
072: static final int RS3_NUM_LIVE = 16;
073:
074: /** RS_VERSION offset */
075: static final int RS4_VERSION = 20;
076:
077: /** RS_LAST_MODIFIED offset */
078: static final int RS5_LAST_MODIFIED = 24;
079:
080: /** RS_START_OF_DATA offset */
081: static final int RS6_DATA_SIZE = 32;
082:
083: /** RS_START_OF_DATA offset */
084: static final int RS7_FREE_SIZE = 36;
085:
086: /** Size of the db header */
087: static final int DB_HEADER_SIZE = 40;
088:
089: /** pre initialized RecordStore header structure */
090: static final byte[] DB_SIGNATURE = { (byte) 'm', (byte) 'i',
091: (byte) 'd', (byte) 'p', (byte) '-', (byte) 'r', (byte) 'm',
092: (byte) 's' };
093:
094: /** used to compact the records of the record store */
095: static final int COMPACT_BUFFER_SIZE = 1024;
096:
097: /**
098: * Each block starts with an 8 byte header
099: * First 4 bytes is the recordId or -1 if it is a free block
100: * Second 4 bytes is the size of the data in the block
101: * The data immediately follows the header
102: * If the length of the data is not a multiple of 8 the data is padded
103: *
104: * Things that need to be done by the header code
105: *
106: */
107: /** Size of the block header */
108: static final int BLOCK_HEADER_SIZE = 8;
109:
110: /**
111: * Internal indicator for AUTHMODE_ANY with read only access
112: * AUTHMODE_ANY_RO has a value of 2.
113: */
114: final static int AUTHMODE_ANY_RO = 2;
115:
116: /**
117: * Changes the access mode for this RecordStore. The authorization
118: * mode choices are:
119: *
120: * <ul>
121: * <li><code>AUTHMODE_PRIVATE</code> - Only allows the MIDlet
122: * suite that created the RecordStore to access it. This
123: * case behaves identically to
124: * <code>openRecordStore(recordStoreName,
125: * createIfNecessary)</code>.</li>
126: * <li><code>AUTHMODE_ANY</code> - Allows any MIDlet to access the
127: * RecordStore. Note that this makes your recordStore
128: * accessible by any other MIDlet on the device. This
129: * could have privacy and security issues depending on
130: * the data being shared. Please use carefully.</li>
131: * </ul>
132: *
133: * <p>The owning MIDlet suite may always access the RecordStore and
134: * always has access to write and update the store. Only the
135: * owning MIDlet suite can change the mode of a RecordStore.</p>
136: *
137: * @param authmode the mode under which to check or create access.
138: * Must be one of AUTHMODE_PRIVATE or AUTHMODE_ANY.
139: * @param writable true if the RecordStore is to be writable by
140: * other MIDlet suites that are granted access
141: *
142: * @exception RecordStoreException if a record store-related
143: * exception occurred
144: * @exception SecurityException if this MIDlet Suite is not
145: * allowed to change the mode of the RecordStore
146: * @exception IllegalArgumentException if authmode is invalid
147: */
148: void setMode(int authmode, boolean writable)
149: throws RecordStoreException;
150:
151: /**
152: * This method is called when the MIDlet requests to have the
153: * record store closed. Note that the record store will not
154: * actually be closed until closeRecordStore() is called as many
155: * times as openRecordStore() was called. In other words, the
156: * MIDlet needs to make a balanced number of close calls as open
157: * calls before the record store is closed.
158: *
159: * <p>When the record store is closed, all listeners are removed
160: * and all RecordEnumerations associated with it become invalid.
161: * If the MIDlet attempts to perform
162: * operations on the RecordStore object after it has been closed,
163: * the methods will throw a RecordStoreNotOpenException.
164: *
165: * @exception RecordStoreNotOpenException if the record store is
166: * not open
167: * @exception RecordStoreException if a different record
168: * store-related exception occurred
169: */
170: void closeRecordStore() throws RecordStoreNotOpenException,
171: RecordStoreException;
172:
173: /**
174: * Get the authorization mode for this record store.
175: *
176: * @return authorization mode
177: */
178: int getAuthMode();
179:
180: /**
181: * Each time a record store is modified (by
182: * <code>addRecord</code>, <code>setRecord</code>, or
183: * <code>deleteRecord</code> methods) its <em>version</em> is
184: * incremented. This can be used by MIDlets to quickly tell if
185: * anything has been modified.
186: *
187: * The initial version number is implementation dependent.
188: * The increment is a positive integer greater than 0.
189: * The version number increases only when the RecordStore is updated.
190: *
191: * The increment value need not be constant and may vary with each
192: * update.
193: *
194: * @return the current record store version
195: */
196: int getVersion() throws RecordStoreNotOpenException;
197:
198: /**
199: * Returns the number of records currently in the record store.
200: *
201: * @return the number of records currently in the record store
202: */
203: int getNumRecords();
204:
205: /**
206: * Returns the amount of space, in bytes, that the record store
207: * occupies. The size returned includes any overhead associated
208: * with the implementation, such as the data structures
209: * used to hold the state of the record store, etc.
210: *
211: * @return the size of the record store in bytes
212: */
213: int getSize();
214:
215: /**
216: * Returns the amount of additional room (in bytes) available for
217: * this record store to grow. Note that this is not necessarily
218: * the amount of extra MIDlet-level data which can be stored,
219: * as implementations may store additional data structures with
220: * each record to support integration with native applications,
221: * synchronization, etc.
222: *
223: * @return the amount of additional room (in bytes) available for
224: * this record store to grow
225: */
226: int getSizeAvailable();
227:
228: /**
229: * Returns the last time the record store was modified, in the
230: * format used by System.currentTimeMillis().
231: *
232: * @return the last time the record store was modified, in the
233: * format used by System.currentTimeMillis()
234: */
235: long getLastModified();
236:
237: /**
238: * Returns the recordId of the next record to be added to the
239: * record store. This can be useful for setting up pseudo-relational
240: * relationships. That is, if you have two or more
241: * record stores whose records need to refer to one another, you can
242: * predetermine the recordIds of the records that will be created
243: * in one record store, before populating the fields and allocating
244: * the record in another record store. Note that the recordId returned
245: * is only valid while the record store remains open and until a call
246: * to <code>addRecord()</code>.
247: *
248: * @return the recordId of the next record to be added to the
249: * record store
250: */
251: int getNextRecordID();
252:
253: /**
254: * Adds a new record to the record store. The recordId for this
255: * new record is returned. This is a blocking atomic operation.
256: * The record is written to persistent storage before the
257: * method returns.
258: *
259: * @param data the data to be stored in this record. If the record
260: * is to have zero-length data (no data), this parameter may be
261: * null.
262: * @param offset the index into the data buffer of the first
263: * relevant byte for this record
264: * @param numBytes the number of bytes of the data buffer to use
265: * for this record (may be zero)
266: *
267: * @return the recordId for the new record
268: *
269: * @exception RecordStoreNotOpenException if the record store is
270: * not open
271: * @exception RecordStoreException if a different record
272: * store-related exception occurred
273: * @exception RecordStoreFullException if the operation cannot be
274: * completed because the record store has no more room
275: * @exception SecurityException if the MIDlet has read-only access
276: * to the RecordStore
277: */
278: int addRecord(byte[] data, int offset, int numBytes)
279: throws RecordStoreNotOpenException, RecordStoreException,
280: RecordStoreFullException;
281:
282: /**
283: * The record is deleted from the record store. The recordId for
284: * this record is NOT reused.
285: *
286: * @param recordId the ID of the record to delete
287: *
288: * @exception RecordStoreNotOpenException if the record store is
289: * not open
290: * @exception InvalidRecordIDException if the recordId is invalid
291: * @exception RecordStoreException if a general record store
292: * exception occurs
293: * @exception SecurityException if the MIDlet has read-only access
294: * to the RecordStore
295: */
296: void deleteRecord(int recordId) throws RecordStoreNotOpenException,
297: InvalidRecordIDException, RecordStoreException;
298:
299: /**
300: * Returns the size (in bytes) of the MIDlet data available
301: * in the given record.
302: *
303: * @param recordId the ID of the record to use in this operation
304: *
305: * @return the size (in bytes) of the MIDlet data available
306: * in the given record
307: *
308: * @exception RecordStoreNotOpenException if the record store is
309: * not open
310: * @exception InvalidRecordIDException if the recordId is invalid
311: * @exception RecordStoreException if a general record store
312: * exception occurs
313: */
314: int getRecordSize(int recordId) throws RecordStoreNotOpenException,
315: InvalidRecordIDException, RecordStoreException;
316:
317: /**
318: * Returns the data stored in the given record.
319: *
320: * @param recordId the ID of the record to use in this operation
321: * @param buffer the byte array in which to copy the data
322: * @param offset the index into the buffer in which to start copying
323: *
324: * @exception RecordStoreNotOpenException if the record store is
325: * not open
326: * @exception InvalidRecordIDException if the recordId is invalid
327: * @exception RecordStoreException if a general record store
328: * exception occurs
329: * @exception ArrayIndexOutOfBoundsException if the record is
330: * larger than the buffer supplied
331: *
332: * @return the number of bytes copied into the buffer, starting at
333: * index <code>offset</code>
334: * @see #setRecord
335: */
336: int getRecord(int recordId, byte[] buffer, int offset)
337: throws RecordStoreNotOpenException,
338: InvalidRecordIDException, RecordStoreException;
339:
340: /**
341: * Returns a copy of the data stored in the given record.
342: *
343: * @param recordId the ID of the record to use in this operation
344: *
345: * @exception RecordStoreNotOpenException if the record store is
346: * not open
347: * @exception InvalidRecordIDException if the recordId is invalid
348: * @exception RecordStoreException if a general record store
349: * exception occurs
350: *
351: * @return the data stored in the given record. Note that if the
352: * record has no data, this method will return null.
353: * @see #setRecord
354: */
355: byte[] getRecord(int recordId) throws RecordStoreNotOpenException,
356: InvalidRecordIDException, RecordStoreException;
357:
358: /**
359: * Sets the data in the given record to that passed in. After
360: * this method returns, a call to <code>getRecord(int recordId)</code>
361: * will return an array of numBytes size containing the data
362: * supplied here.
363: *
364: * @param recordId the ID of the record to use in this operation
365: * @param newData the new data to store in the record
366: * @param offset the index into the data buffer of the first
367: * relevant byte for this record
368: * @param numBytes the number of bytes of the data buffer to use
369: * for this record
370: *
371: * @exception RecordStoreNotOpenException if the record store is
372: * not open
373: * @exception InvalidRecordIDException if the recordId is invalid
374: * @exception RecordStoreException if a general record store
375: * exception occurs
376: * @exception RecordStoreFullException if the operation cannot be
377: * completed because the record store has no more room
378: * @exception SecurityException if the MIDlet has read-only access
379: * to the RecordStore
380: * @see #getRecord
381: */
382: void setRecord(int recordId, byte[] newData, int offset,
383: int numBytes) throws RecordStoreNotOpenException,
384: InvalidRecordIDException, RecordStoreException,
385: RecordStoreFullException;
386:
387: /**
388: * Returns all of the recordId's currently in the record store.
389: *
390: * @return an array of the recordId's currently in the record store
391: * or null if the record store is closed.
392: */
393: int[] getRecordIDs();
394:
395: /**
396: * Returns data base file associated with this record store
397: *
398: * @return data base file
399: */
400: AbstractRecordStoreFile getDbFile();
401:
402: /**
403: * Creates data base index file associated with this record store
404: *
405: * @return data base index file
406: * @exception IOException if failed to create a file
407: */
408: AbstractRecordStoreFile createIndexFile(int suiteId, String name)
409: throws IOException;
410: }
|