Recipe 26.7 Program: DBM


This program lets you use the original Unix DBM (database access method) routines from Java. DBM is actually emulated using the newer Berkeley Database (DB) routines, but the DBM interface is more traditional and simpler. DBM was used in Recipe Recipe 20.3 to provide a name-to-login database, which is similar to how many modern Unixes actually store name and password information. That recipe also showed how to use it to display your Netscape history, even under Windows.

I'll now show the Java version of the DBM library, DBM.java, in Example 26-13. To compile it, you need the DBM routines installed.

Example 26-13. DBM.java
import java.io.*; /** This class provides a dbm-compatible interface to the Unix-style  * database access methods described in dbm(3) (which is on some Unixes  * a front-end to db(3)).  * <p>Each unique record in the database is a unique key/value pair,  * similar to a java.util.Hashtable but stored on a persistent medium, not  * kept in memory. Dbm was originally optimized for Unix for fast  * access to individual key/value pairs.</p>  */ public class DBM {     /** Since you can only have one DBM database in use at a time due      * to implementation restrictions, we enforce this rule with a      * class-wide boolean.      */     protected static boolean inuse = false;     /** Save the filename for messages, etc. */     protected String fileName;     /** Construct a DBM given its filename */     public DBM(String file) {         synchronized(this) {             if (inuse)                 throw new IllegalArgumentException(                     "Only one DBM object at a time per Java Machine");             inuse = true;         }         fileName = file;         int retCode = dbminit(fileName);         if (retCode < 0)             throw new IllegalArgumentException(                 "dbminit failed, code = " + retCode);     }     // Static code blocks are executed once, when class file is loaded.     // This is here to ensure that the shared library gets loaded.     static {         System.loadLibrary("jdbm");     }     protected ByteArrayOutputStream bo;     /** serialize an Object to byte array. */     protected byte[] toByteArray(Object o) throws IOException {         if (bo == null)             bo = new ByteArrayOutputStream(1024);         bo.reset( );         ObjectOutputStream os = new ObjectOutputStream(bo);         os.writeObject(o);         os.close( );         return bo.toByteArray( );     }     /** un-serialize an Object from a byte array. */     protected Object toObject(byte[] b) throws IOException {         Object o;         ByteArrayInputStream bi = new ByteArrayInputStream(b);         ObjectInputStream os = new ObjectInputStream(bi);         try {             o = os.readObject( );         } catch (ClassNotFoundException ex) {             // Convert ClassNotFoundException to I/O error             throw new IOException(ex.getMessage( ));         }         os.close( );         return o;     }     protected native int dbminit(String file);     protected native int dbmclose( );     /** Public wrapper for close method. */     public void close( ) {         this.dbmclose( );         inuse = false;     }     protected void checkInUse( ) {         if (!inuse)             throw new IllegalStateException("Method called when DBM not open");     }     protected native byte[] dbmfetch(byte[] key);     /** Fetch using byte arrays */     public byte[] fetch(byte[] key) throws IOException {         checkInUse( );         return dbmfetch(key);     }     /** Fetch using Objects */     public Object fetch(Object key) throws IOException {         checkInUse( );         byte[] datum = dbmfetch(toByteArray(key));         return toObject(datum);     }     protected native int dbmstore(byte[] key, byte[] content);     /** Store using byte arrays */     public void store(byte[] key, byte[] value) throws IOException {         checkInUse( );         dbmstore(key, value);     }     /** Store using Objects */     public void store(Object key, Object value) throws IOException {         checkInUse( );         dbmstore(toByteArray(key), toByteArray(value));     }     protected native int delete(Object key);     public native byte[] firstkey( ) throws IOException;     public Object firstkeyObject( ) throws IOException {         return toObject(firstkey( ));     }     public native byte[] nextkey(byte[] key) throws IOException;     public Object nextkey(Object key) throws IOException {         byte[] ba = nextkey(toByteArray(key));         if (ba == null)             return null;         return toObject(ba);     }     public String toString( ) {         return "DBM@" + hashCode( ) + "[" + fileName + "]";     } }

Notice how the methods toByteArray( ) and toObject( ), the inverses of each other, convert between an object and an array of bytes using ByteArrayStreams. These provide the functionality of reading from or writing to a buffer that is in memory, instead of the usual buffer that has been read from or written to a disk file or socket.

See Also

A more complete and widely used implementation of DBM for Java is available from SleepyCat Software, the heirs-apparent to the Berkeley DBM software. Their SleepyCat DBM can be downloaded for free, in source form, under the Berkeley (University of California at Berkeley) software license. Check out http://www.sleepycat.com.



Java Cookbook
Java Cookbook, Second Edition
ISBN: 0596007019
EAN: 2147483647
Year: 2003
Pages: 409
Authors: Ian F Darwin

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net