/* * SimpleDB.java * * Created on March 29, 2003, 1:25 PM */ package downey; import java.util.*; import java.io.*; /** * This class allows for read and write access to a simple database. It is * in a package named downey

The * database is stored as a HashMap, so it can store any object. There are * some helper functions to assist for changing a String[] to an ArrayList * and from an ArrayList to a String[]. * Since the database is being serialized, it should only contain objects * that belong to the standard collections, and String[] is not one of them. * @author Tim Downey */ public class SimpleDB { /* *The file name that corresponds to the DB */ protected String m_fileName; /* *Name of HashMap that contains DB */ protected HashMap m_database; /* *Flag for determing if DB is open */ protected boolean isOpen = false; /** Creates a new instance of SimpleDB * @param fileName The name of the file to open. The file should * already exist and should be readable and writable * by the world, but not by the group (606) * *

Create an instance variable for the database

* downey.SimpleDB m_database; *

Construct the object only once in your servlet. The best place * to call it is in the init method

* * m_database = new downey.SimpleDB("/aul/homes/dlett004/cgs4825/java-servlets/WEB-INF/classes/myFile.db"); */ public SimpleDB(String fileName) { init(fileName); } /** A default constructor for use with a tag lib. */ public SimpleDB() { isOpen = false; } /** Reinitializes a DB. This does not need to be called. It is here * only to assist in using the SimpleDB with a tag lib. * @param fileName The name of the file to open. The file should * already exist and should be readable and writable * by the world, but not by the group (606) */ public void init(String fileName) { m_fileName = fileName; openDatabase(); } /** init with no parameters. It will only create a DB if the setFileName method * has already been called. Used with a tag lib */ public void init() { if (m_fileName == null || m_fileName.trim().equals("")) { System.out.println("Cannot init: file name not set"); return; } openDatabase(); } /** Used in a tag lib. Sets the fileName for a * subsequent call to init() */ public void setFileName(String fileName) { m_fileName = fileName; } /** Used in a tag lib. Completes the propery for fileName */ public String getFileName() { return m_fileName; } /* Opens the database. It is called when the SimpleDB object is constructed. */ protected synchronized void openDatabase () { File f = new File(m_fileName); if (f.exists()) { try { ObjectInputStream in = new ObjectInputStream (new FileInputStream(f)); m_database = (HashMap)in.readObject(); in.close(); } catch (IOException ioe) { System.out.println("Couldn't open database file\n" + ioe); m_database = new HashMap(); } catch (ClassNotFoundException nfe) { System.out.println("Couldn't find class\n" + nfe); m_database = new HashMap(); } } else { int index = m_fileName.lastIndexOf('/'); File p = null; String path = null; if (index > -1) { path = m_fileName.substring(0, index); p = new File(path); } if (p != null && !p.exists()) { System.out.println("Error: " + path + " is an invalid path. Creating empty DB."); } else { System.out.println(m_fileName + " does not exist. Creating empty DB."); } m_database = new HashMap(); } isOpen = true; } /* Call this method to write the entire contents of the database to disk. This * should be called after every time something is added, just in case there is * a server crash. */ protected synchronized void saveDatabase() { if (!isOpen) { System.out.println("Cannot save: no database is initialized"); return; } File f = new File(m_fileName); try { ObjectOutputStream out = new ObjectOutputStream (new FileOutputStream(f)); out.writeObject(m_database); out.close(); } catch (IOException ioe) { System.out.println("Couldn't save file\n" + ioe); } } /** Read a record object from the database. * @param key This is the string key used to access the database. * @return The Object that is associated with the key *

It will be necessary to cast * the return type to the correct class in your code. It is up to you to insure * that you retrieve the correct type.

* MyRecordClass record = (MyRecordClass) m_database.readRecord("fred"); */ public Object readRecord(String key) { if (!isOpen) { System.out.println("Cannot read: no database is initialized"); return null; } return m_database.get(key); } /** This will either add or update the object associated with the given key. * * @param key The string used to access that database * @param obj The object to be added to the database *

* It is not necessary to cast the parameter to any type, since all objects * are derived from Object.

* m_database.updateRecord("fred", record); * */ public synchronized void updateRecord(String key, Object obj) { if (!isOpen) { System.out.println("Cannot update: no database is initialized"); return; } m_database.put(key, obj); saveDatabase(); } /** This is a helper function for creating an ArrayList from a String[]. * * @param values The String[] to be converted * @return The ArrayList that is created with all the elements of the String[] *

Since String[] are not of the standard collections, it is more difficult * to serialize. If you need to save a String[] into the database, first * convert it to an ArrayList. ArrayList is part of the standard collections * and is easily serialized.

* String str[] = request.getParamterValues("team"); *
ArrayList list = m_database.makeList(str);
*/ public ArrayList makeList(String[] values) { ArrayList list = new ArrayList(); for(int i=0; i < values.length; i++) { list.add(values[i]); } return list; } /** This is a helper function for creating a String[] from an ArrayList. * This is the counterpart of makeList. * @param list The ArrayList to be converted * @return The String[] that is created with all the elements of the ArrayList *

If a String[] has been converted * to an ArrayList and stored in the database, then retrieve the ArrayList * from the database and use the method to recreate the original String[] *
String[] str = Downey.makeArray(list); */ public String[] makeArray(ArrayList list) { String[] values = new String[list.size()]; for(int i=0; i < list.size(); i++) { values[i] = (String) list.get(i); } return values; } /** Delete all the elements in the database. * If you need to erase all the elements in the database, then call this * method. It will erase the contents of the HashMap and of the file. *

m_database.eraseDatabase(); */ public synchronized void eraseDatabase() { if (!isOpen) { System.out.println("Cannot erase: no database is initialized"); return; } m_database = new HashMap(); saveDatabase(); } /** Returns an Iterator of the keys in the DB *@return Iterator of keys */ public Iterator keyIterator() { if (!isOpen) { System.out.println("Cannot get iterator: no database is initialized"); return null; } return m_database.keySet().iterator(); } /** Returns an Iterator of the values in the DB *@return Iterator of values */ public Iterator valueIterator() { if (!isOpen) { System.out.println("Cannot get iterator: no database is initialized"); return null; } return m_database.values().iterator(); } }