/* * 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");
*
*/
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
*
ArrayList list = m_database.makeList(str);
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();
}
}