/* * @(#)Database.java 1.5 01/08/21 * Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved. * * This software is the confidential and proprietary information of Sun * Microsystems, Inc. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Sun. * * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING * THIS SOFTWARE OR ITS DERIVATIVES. */ package example.stock; import javax.microedition.rms.*; import java.util.*; import java.io.EOFException; /** * This class provides a wrapper class for the * RecordStore class. * It allows for easier addition and deletion as well as better searching and * updating of records. The used recordIDs are kept in a Vector * which we use to access the indices of the records. The last used recordID * is stored at the beginning of the database and when the database is opened, * each recordID up to the last one used is tested to see if a record exists in * that position and a new Vector of used recordIDs * is generated. */ public abstract class Database { /** * The database storing all the records and the last * used recordID in position 1 */ protected volatile RecordStore database = null; /** * The Vector of used recordIDs that are in the database */ protected volatile Vector recordIDs = null; /** * The last used ID in the database */ protected int lastID = 1; /** * The object used to compare two records and see if they are equal */ protected RecordComparator rc = null; /** * Initializes the database and if it's not a new database, loads the * recordID of the last record out of the first position in the * RecordStore. We have stored it there when we closed the * database, then checks each ID from 1 to lastID to see if they exist in * the database and then add the IDs that exist to the recordIDs * Vector * * @param fileName The name of the RecordStore to open * @throws RecordStoreNotFoundException is thrown if the * RecordStore indicated with fileName * cannot be found * @throws RecordStoreException is thrown when a general * exception occurs in a RecordStore operation * @throws RecordStoreFullException is thrown when the * storage system is is full */ public void open(String fileName) throws RecordStoreNotFoundException, RecordStoreException, RecordStoreFullException { database = RecordStore.openRecordStore(fileName, true); recordIDs = new Vector(); try { if (database.getNumRecords() != 0) { try { lastID = Integer.valueOf( new String(database.getRecord(1))).intValue(); for (int i = 1; i try { database.getRecord(i); recordIDs.addElement(new Integer(i)); } catch (RecordStoreException rs) {} } } catch (InvalidRecordIDException iri) { throw new RecordStoreException(iri.getMessage()); } } } catch (RecordStoreNotOpenException rsno) { throw new RecordStoreException(rsno.getMessage()); } } /** * Close the database and remove it from persistant * storage if it is empty * * @throws RecordStoreNotOpenException is thrown when trying * to close a RecordStore that is not open * @throws RecordStoreException is thrown when a general * exception occurs in a RecordStore operation */ public void close() throws RecordStoreNotOpenException, RecordStoreException { if (database.getNumRecords() == 0) { String fileName = database.getName(); database.closeRecordStore(); database.deleteRecordStore(fileName); } else { database.closeRecordStore(); } } /** * Remove the database from persistant storage * * @param fileName the name of the RecordStore to remove */ public void cleanUp(String fileName) throws RecordStoreNotFoundException, RecordStoreException { RecordStore.deleteRecordStore(fileName); open(fileName); } /** * Add the record to the database * Add the recordID to our vector * Update the database's last ID counter * * @param record The record data to be added to the database * @throws RecordStoreNotOpenException is thrown when * trying to close a RecordStore that is not open * @throws RecordStoreFullException is thrown when the storage * system is is full * @throws RecordStoreException is thrown when a general * exception occurs in a RecordStore operation */ public synchronized void add(String record) throws RecordStoreNotOpenException, RecordStoreFullException, RecordStoreException { if (database.getNumRecords() != 0) { database.addRecord(record.getBytes(), 0, record.getBytes().length); recordIDs.addElement(new Integer(++lastID)); database.setRecord(1, (String.valueOf(lastID)).getBytes(), 0, (String.valueOf(lastID)).length()); } else { recordIDs.addElement(new Integer(++lastID)); database.addRecord((String.valueOf(lastID)).getBytes(), 0, (String.valueOf(lastID)).length()); try { database.addRecord(record.getBytes(), 0, record.getBytes().length); } catch (RecordStoreException rs) { recordIDs.removeElement(new Integer(lastID--)); database.setRecord(1, (String.valueOf(lastID)).getBytes(), 0, (String.valueOf(lastID)).length()); throw rs; } } } /** * Delete the record from the database and remove that recordID from the * vector of used recordIDs * * @param s The name of the record to delete from the database * @throws RecordStoreNotOpenException is thrown when trying * to close a RecordStore that is not open * @throws RecordStoreException is thrown when a general * exception occurs in a RecordStore operation */ public synchronized void delete(String s) throws RecordStoreNotOpenException, RecordStoreException { action(s, null, 0); } /** * Find and return a record * * @return The record that we're looking for or * null if not found * @param s The name of the record to search for * @throws RecordStoreNotOpenException is thrown when trying * to close a RecordStore that is not open * @throws RecordStoreException is thrown when a general * exception occurs in a RecordStore operation */ public synchronized String search(String s) throws RecordStoreNotOpenException, RecordStoreException { return (String) action(s, null, 1); } /** * Update the record with the name s with the data * in the byte[] array * * @param s The name of the record to update * @param data the new data to update the record with * @throws RecordStoreNotOpenException is thrown when trying * to close a RecordStore that is not open * @throws RecordStoreFullException is thrown when the storage * system is is full * @throws RecordStoreException is thrown when a general * exception occurs in a RecordStore operation */ public synchronized void update(String s, byte[] data) throws RecordStoreNotOpenException, RecordStoreFullException, RecordStoreException { action(s, data, 2); } /** * Go to the index of the record specified by s and perform * an action. Either an update, search or deletion. This method is for * code compaction as the process for updating, searching and * deleting varies only slightly. * * @param s The name of the record to perform the action on * @param data Data to use in the action * @param action What to do. 0 = delete, 1 = search, 2 = update * @throws RecordStoreNotOpenException is thrown when trying * to close a RecordStore that is not open * @throws RecordStoreFullException is thrown when the storage * system is is full * @throws RecordStoreException is thrown when a general * exception occurs in a RecordStore operation */ private synchronized Object action(String s, byte[] data, int action) throws RecordStoreNotOpenException, RecordStoreFullException, RecordStoreException { if ((action != 1) && (recordIDs.size() == 0)) { throw new RecordStoreException(); } Enumeration IDs = recordIDs.elements(); while (IDs.hasMoreElements()) { int index = ((Integer) IDs.nextElement()).intValue(); try { if (rc.compare(database.getRecord(index), s.getBytes()) == RecordComparator.EQUIVALENT) { switch (action) { case 0: database.deleteRecord(index); recordIDs.removeElement(new Integer(index)); return null; case 1: return new String(database.getRecord(index)); case 2: database.setRecord(index, data, 0, data.length); return null; default: break; } } } catch (InvalidRecordIDException iri) { throw new RecordStoreException(iri.getMessage()); } } return null; } /** * Return the number of records in the database * * @return the number of records in the database * @throws RecordStoreNotOpenException is thrown when trying * to close a RecordStore that is not open */ public int getNumRecords() throws RecordStoreNotOpenException { return database.getNumRecords(); } }