You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jdo-commits@db.apache.org by mb...@apache.org on 2005/05/22 20:40:21 UTC

svn commit: r171355 [5/31] - in /incubator/jdo/trunk/fostore20: ./ src/ src/conf/ src/java/ src/java/org/ src/java/org/apache/ src/java/org/apache/jdo/ src/java/org/apache/jdo/impl/ src/java/org/apache/jdo/impl/fostore/ test/ test/conf/ test/fsuid2/ test/fsuid2/org/ test/fsuid2/org/apache/ test/fsuid2/org/apache/jdo/ test/fsuid2/org/apache/jdo/pc/ test/java/ test/java/org/ test/java/org/apache/ test/java/org/apache/jdo/ test/java/org/apache/jdo/impl/ test/java/org/apache/jdo/impl/fostore/ test/java/org/apache/jdo/pc/ test/java/org/apache/jdo/pc/appid/ test/java/org/apache/jdo/pc/empdept/ test/java/org/apache/jdo/pc/serializable/ test/java/org/apache/jdo/pc/xempdept/ test/java/org/apache/jdo/test/ test/java/org/apache/jdo/test/query/ test/java/org/apache/jdo/test/util/ test/jdo/ test/jdo/org/ test/jdo/org/apache/ test/jdo/org/apache/jdo/ test/jdo/org/apache/jdo/pc/ test/jdo/org/apache/jdo/pc/appid/ test/jdo/org/apache/jdo/pc/empdept/ test/jdo/org/apache/jdo/pc/serializable/ test/jdo/org/apache/jdo/pc/xempdept/

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreConnector.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreConnector.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreConnector.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreConnector.java Sun May 22 11:40:13 2005
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.IOException;
+
+import javax.jdo.JDOException;
+import javax.jdo.JDODataStoreException;
+import javax.jdo.JDOFatalInternalException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.store.Connector;
+import org.apache.jdo.util.I18NHelper;
+
+/**
+* FOStoreConnector represents a connection to the FOStoreDatabase.
+*
+* @author Dave Bristor
+*/
+class FOStoreConnector implements Connector {
+    /** @see org.apache.jdo.store.Connector#setRollbackOnly */
+    private boolean rollbackOnly = false;
+
+    /** I18N support. */
+    private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+    /** Logger */
+    static final Log logger = LogFactory.getFactory().getInstance(
+        "org.apache.jdo.impl.fostore"); // NOI18N
+    
+    /**
+    * Message in which this Connector buffers requests for the store.
+    */
+    private final Message message;
+
+    /**
+    * Datasource to which this Connector writes its Message.
+    */
+    private final FOStorePMF pmf;
+
+    /**
+    * Connection for interacting with store.
+    */
+    FOStoreClientConnection connection = null;
+    
+    /**
+    * True if we can release this connection after flushing.  By default we
+    * can; affected by transactions beginning and ending and their types.
+    */
+    private boolean okToReleaseConnection = true;
+
+    /** True if flush is in progress. */
+    private boolean busy = false;
+    
+    FOStoreConnector(FOStorePMF pmf) {
+        this.pmf = pmf;
+        this.message = new Message(this);
+    }
+
+    //
+    // Implement Connector
+    //
+
+    /**
+     * @see org.apache.jdo.store.Connector#begin
+     */
+    public void begin(boolean optimistic) {
+        assertNotRollbackOnly();
+        
+        // If transaction is optimistic, then we can release the connection as
+        // soon as data is flushed.  If it's datastore, then we can't release
+        // the connection until after commit/rollback.
+        this.okToReleaseConnection = optimistic;
+        
+        if (logger.isDebugEnabled()) {
+            logger.debug(
+                "FOConnector.begin: okToReleaseConnection=" +  // NOI18N
+                okToReleaseConnection);
+        }
+
+        try {
+            RequestFactory rf = pmf.getRequestFactory();
+            BeginTxRequest request =
+                rf.getBeginTxRequest(message, pmf, optimistic);
+            request.doRequest();
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                getClass(), "update", ex); // NOI18N
+        } catch (JDOException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            throw new FOStoreFatalInternalException(
+                getClass(), "update", ex); // NOI18N
+        }
+    }
+
+    /**
+     * @see org.apache.jdo.store.Connector#beforeCompletion
+     */
+    public void beforeCompletion() {
+        assertNotRollbackOnly();
+        
+        // Nothing to do.
+    }
+
+    /**
+     * Get a connection, process the message by using that connection to
+     * interact with the database, read back the reply, release the
+     connection.
+     * @see org.apache.jdo.store.Connector#flush
+     */
+    public void flush() {
+        assertNotRollbackOnly();
+        assertNotBusy("flush"); // NOI18N
+        busy = true;
+
+        try {
+        
+            if (logger.isDebugEnabled()) {
+                logger.debug(
+                  "FOConnector.flush: " + // NOI18N
+                  "okToReleaseConnection=" + okToReleaseConnection + // NOI18N
+                  ", connection=" + connection); // NOI18N
+            }
+
+            if (message.hasRequests()) {
+                if (logger.isTraceEnabled()) message.dump();
+
+                if (connection == null) {
+                    FOStoreConnectionFactory cf =
+                        (FOStoreConnectionFactory)pmf.getConnectionFactory();
+                    connection = (FOStoreClientConnection)cf.getConnection();
+                }
+
+                // Now send the message and process it in the store
+                try {
+                    message.processInStore(connection, okToReleaseConnection);
+                } finally {
+                    if (okToReleaseConnection) {
+                        connection = null;
+                    }
+                }
+            }
+        } finally {
+            busy = false;
+        }
+    }
+
+    /**
+    * Add a CommitRequest to the connector's message, and send it to the
+    * store.  Then close the connection.
+    * @see org.apache.jdo.store.Connector#commit
+    */
+    public synchronized void commit() {
+        assertNotRollbackOnly();
+        assertNotBusy("commit"); // NOI18N
+        
+        try {
+            if (logger.isDebugEnabled()) {
+                logger.debug("FOConnector.commit"); // NOI18N
+            }
+
+            RequestFactory rf = pmf.getRequestFactory();
+            CommitRequest request = rf.getCommitRequest(message, pmf);
+
+            request.doRequest();
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                this.getClass(), "commit", ex); // NOI18N
+        } catch (JDOException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            throw new FOStoreFatalInternalException(
+                getClass(), "commit", ex); // NOI18N
+        } finally {
+            // Now that we've commited, we can release the connection.
+            okToReleaseConnection = true;
+            flush();
+        }
+    }
+
+    /**
+     * If rollbackOnly is set, then the store has already done a
+     * rollback, so we don't do one now (but neither do we throw an
+     * exception, as do other methds).
+     * @see org.apache.jdo.store.Connector#rollback
+     * @see org.apache.jdo.impl.fostore.ReplyHandler#processReplies
+     */
+    public synchronized void rollback() {
+        assertNotBusy("rollback"); // NOI18N
+        if (logger.isDebugEnabled()) {
+            logger.debug(
+                "FOConnector.rollback, RBO=" + rollbackOnly); // NOI18N
+        }
+        
+        if (! rollbackOnly) {
+            try {
+                RequestFactory rf = pmf.getRequestFactory();
+                RollbackRequest request = rf.getRollbackRequest(message, pmf);
+                
+                request.doRequest();
+            } catch (IOException ex) {
+                throw new FOStoreFatalIOException(
+                    this.getClass(), "rollback", ex); // NOI18N
+            } catch (JDOException ex) {
+                throw ex;
+            } catch (Exception ex) {
+                throw new FOStoreFatalInternalException(
+                    getClass(), "rollback", ex); // NOI18N
+            } finally {
+                // Now that we've rolled back, we can release the connection.
+                okToReleaseConnection = true;
+                flush();
+            }
+        }
+    }
+
+    /**
+     * @see org.apache.jdo.store.Connector#setRollbackOnly
+     */
+    public void setRollbackOnly() {
+        rollbackOnly = true;
+    }
+
+    /**
+     * @see org.apache.jdo.store.Connector#getRollbackOnly
+     */
+    public boolean getRollbackOnly() {
+        return rollbackOnly;
+    }
+
+    //
+    // Implementation
+    //
+
+    /**
+     * Provides the Message which this this connector uses to send data to the
+     * store.
+     */
+    Message getMessage() {
+        assertNotRollbackOnly();
+        assertNotBusy("getMessage"); // NOI18N
+        
+        return message;
+    }
+
+    private void assertNotRollbackOnly() {
+        if (rollbackOnly) {
+            throw new JDODataStoreException(
+                msg.msg("EXC_RollbackOnly")); // NOI18N
+        }
+    }
+
+    private void assertNotBusy(String methodName) {
+        if (busy) {
+            throw new FOStoreFatalInternalException(
+              getClass(), methodName,
+                msg.msg("EXC_Busy")); // NOI18N
+        }
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreDatabase.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreDatabase.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreDatabase.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreDatabase.java Sun May 22 11:40:13 2005
@@ -0,0 +1,574 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.File;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+import java.util.Set;
+import java.util.HashMap;
+
+import javax.jdo.JDOFatalUserException;
+import javax.jdo.JDOFatalException;
+import javax.jdo.JDOFatalDataStoreException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.util.I18NHelper;
+import org.apache.jdo.util.Pool;
+import org.netbeans.mdr.persistence.Storage;
+import org.netbeans.mdr.persistence.SinglevaluedIndex;
+import org.netbeans.mdr.persistence.StorageBadRequestException;
+import org.netbeans.mdr.persistence.StorageException;
+import org.netbeans.mdr.persistence.Streamable;
+
+/**
+* File/Object Store Database, using an underlying Btree implementation.
+*
+* @author Dave Bristor
+*/
+class FOStoreDatabase {
+    
+    /** We manage a map of pools of databases by database name.
+     */
+    private static final HashMap databaseMap = new HashMap();
+    
+    private static final int poolSize = 1;
+    
+    // We delegate all calls to this storage.  Not final, because for
+    // rollback's sake we have to close and then make a new storage.
+    private FOStoreBtreeStorage storage;
+
+    // Map from provisional IDs to real, datastore-created, durable IDs.
+    //
+    // XXX TBD Remote: Provisional CLID's are per client (PMF).
+    // That is because each client will independently generate its
+    // own set of provisional ID's.  One way to manage this might be for
+    // each client to send a "hello" message when it first connects, with
+    // something like it's IP address and process id.  Future communications
+    // from that same client will contain that same info.  A "goodbye" message
+    // would be nice, too, so that the store can remove any tables that will
+    // not ever be used again.
+    private final HashMap provisionalCLIDs = new HashMap();
+
+    // Same as above, but for OIDs.
+    private final HashMap provisionalOIDs = new HashMap();
+    
+    /** Count the number of connections open on this database.  When the last 
+     * connection closes, then really close the database.
+     */
+    private int openConnections = 0;
+    
+    private DBInfo dbInfo = null;
+    /** Pool for this database.
+     */
+    private Pool pool = null;
+
+    /** I18N support. */
+    private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+    /** Logger */
+    static final Log logger = LogFactory.getFactory().getInstance(
+        "org.apache.jdo.impl.fostore"); // NOI18N
+    
+    /** Find an open database of the given name.  If it is not already open,
+     * open it and put it into the pool.
+     */
+    public synchronized static FOStoreDatabase getDatabase (String dbname, 
+                                                            boolean create) 
+            throws InterruptedException, FOStoreDatabaseException {
+        Pool pool = (Pool) databaseMap.get(dbname);
+        FOStoreDatabase db = null;
+        if (pool == null) {
+            try {
+                db = new FOStoreDatabase (dbname, create);
+            } catch (FOStoreDatabaseException fode) {
+                if (logger.isDebugEnabled()) {
+                    logger.debug(
+                        "FODB:getDatabase exception for new database " + // NOI18N
+                        dbname + " create: " + create); // NOI18N
+                }
+                throw (fode);
+            }
+            pool = new Pool (poolSize);
+            databaseMap.put (dbname, pool);
+            pool.put (db);
+            db.setPool(pool);
+        }
+        if (logger.isDebugEnabled()) {
+            logger.debug("FODB:getDatabase found pool for database " + dbname); // NOI18N
+        }
+        db = (FOStoreDatabase) pool.get();
+        return db;
+    }
+    
+    /** Release the database for other connections to use.
+     */
+    public synchronized static void releaseDatabase (FOStoreDatabase db)
+        throws InterruptedException {
+
+        db.pool.put (db);
+    }
+        
+    /**
+    * Create an FODatabase and create/open the files.
+    * @param name name of database, which is used to name the files
+    * @param isNew true if the database is being created
+    */
+     FOStoreDatabase(String name, boolean isNew)
+        throws FOStoreDatabaseException {
+            // first verify that the directory exists
+            // if not, there is no way to continue
+            // Note, the filename might include a mixture of \ and / as
+            // path separator, make them all / for the lookup
+            int slashIndex = name.replace('\\', '/').lastIndexOf('/');
+            if (slashIndex != -1) { // at least one / in pathname
+                String dirName = name.substring(0, slashIndex);
+                File dir = new File(dirName); // NOI18N
+                if (!existsFile(dir)) {
+                    throw new JDOFatalDataStoreException (
+                        msg.msg("ERR_DirectoryDoesNotExist", name)); // NOI18N
+                }
+            }
+            // XXX the DBInfo is not a singleton; change this code
+            // and DBInfo to support multiple Databases in one VM.
+        if (isNew) {
+            // We must remove a database if one does exist.  This means delete
+            // both the .btd and .btx files.
+            String extensions[] = {"btd", "btx"}; // NOI18N
+            boolean found = false;
+            for (int i = 0; i < extensions.length; i++) {
+                File f = new File(name + "." + extensions[i]); // NOI18N
+                if (existsFile(f)) {
+                    if (! found) {
+                        if (logger.isDebugEnabled()) {
+                            logger.debug("FODB: Deleting existing database " +
+                                           name); // NOI18N
+                        }
+                        found = true;
+                    }
+                    deleteFile(f);
+                }
+            }
+            storage = createBtreeStorage(name, true);
+            dbInfo = new DBInfo(this);
+            dbInfo.store();
+            commitChanges();
+            if (logger.isDebugEnabled()) {
+                logger.debug("FODB: Created database " + name); // NOI18N
+            }
+        } else {
+            storage = createBtreeStorage(name, false);
+            dbInfo = DBInfo.get(this);
+            if (logger.isDebugEnabled()) {
+                logger.debug(
+                    "FODB: Opened existing database " + name); // NOI18N
+            }
+        }
+    }
+
+    /** Verify that this user is authorized to use this database.
+     */
+    public void verifyUserPassword (String user, long timestamp, byte[] secret) {
+        // XXX look up Authentication objects and verify this user is authorized.
+        addConnection();
+    }
+    
+    /** Get the DBInfo for this database.
+     */
+    public DBInfo getDBInfo() {
+        return dbInfo;
+    }
+    
+    /** Associates the specified value with the specified key in this index.
+    * @return true if there was an item in this index that was associated
+    * with the key prior to this call
+    * @param key
+    * @param value
+    * @throws FOStoreDatabaseException
+    */
+    public boolean put(OID key, Object value) throws FOStoreDatabaseException {
+        try {
+            Object keyValue = key.keyValue(storage);
+// Uncomment the next lines to simulate a fatal error during login.
+//            if (null != keyValue)
+//                throw new NullPointerException("fodb: NPE on purpose"); // YYY
+            return storage.getPrimaryIndex().put(keyValue, value);
+        } catch (StorageException ex) {
+            throw new FOStoreDatabaseException(ex);
+        }
+    }
+
+    /** Replaces the original value associated with the specified key in this
+    * index with new value. If no value was associated with this key prior
+    * to this call StorageBadRequestException is thrown.
+    * @param key
+    * @param value
+    * @throws FOStoreDatabaseException
+    */
+    public void replace(OID key, Object value)
+        throws FOStoreDatabaseException {
+
+        try {
+            Object keyValue = key.keyValue(storage);
+            storage.getPrimaryIndex().replace(keyValue, value);
+        } catch (StorageException ex) {
+            throw new FOStoreDatabaseException(ex);
+        }
+    }
+        
+    /** Returns the value to which this index maps the specified key.
+    * StorageBadRequestException is thrown if there is no value for the key.
+    * @return value associated with specified key
+    * @param key
+    * @throws FOStoreDatabaseException
+    */
+    public Object get(OID key)
+        throws FOStoreDatabaseException {
+
+        try {
+            Object keyValue = key.keyValue(storage);
+            return storage.getPrimaryIndex().get(keyValue);
+        } catch (StorageException ex) {
+            throw new FOStoreDatabaseException(ex);
+        }
+    }
+
+    /** Returns the value to which this index maps the specified key
+    * or null if there is no value for this key.
+    * @return value associated with specified key or null
+    * @param key
+    * @throws FOStoreDatabaseException
+    */
+    public Object getIfExists (OID key) throws FOStoreDatabaseException {
+        try {
+            Object keyValue = key.keyValue(storage);
+            return storage.getPrimaryIndex().getIfExists(keyValue);
+        } catch (StorageException ex) {
+            throw new FOStoreDatabaseException(ex);
+        }
+    }
+    
+    /** Returns the unique name of the index in the Storage.
+    * @return The name of this index.
+    */
+    public String getName()  {
+        return storage.getName();
+    }
+
+    /** Returns a set view of the keys contained in this index.
+    * Returned set is read only and may not be modified.
+    * @return keys contained in this index
+    * @throws FOStoreDatabaseException
+    */
+    public Set keySet() throws FOStoreDatabaseException {
+        try {
+            return storage.getPrimaryIndex().keySet();
+        } catch (StorageException ex) {
+            throw new FOStoreDatabaseException(ex);
+        }
+    }
+
+    /** Adds the specified value to values associated in this index with the
+    * specified key. If the index puts limit on number of values associated
+    * with one key and adding value would break this limit, it thorows
+    * StorageBadRequestException.
+    * @param key
+    * @param value
+    * @throws FOStoreDatabaseException
+    */
+    public void add(OID key, Object value) throws FOStoreDatabaseException {
+        try {
+            Object keyValue = key.keyValue(storage);
+            storage.getPrimaryIndex().add(keyValue, value);
+        } catch (StorageException ex) {
+            throw new FOStoreDatabaseException(ex);
+        }
+    }
+    
+    /** Removes all values assosiated in the index with specified key.
+    * @return true if this index changed as a result of this call
+    * @param key
+    * @throws FOStoreDatabaseException
+    */
+    public boolean remove (OID key) throws FOStoreDatabaseException {
+        try {
+            Object keyValue = key.keyValue(storage);
+            return storage.getPrimaryIndex().remove(keyValue);
+        } catch (StorageException ex) {
+            throw new FOStoreDatabaseException(ex);
+        }
+    }
+
+    public void commitChanges() throws FOStoreDatabaseException {
+        if (logger.isDebugEnabled()) logger.debug("FODB.commitChanges"); // NOI18N
+
+        // Need to have privileges to perform this operation.
+        final FOStoreBtreeStorage storage1 = storage;
+        try {
+            AccessController.doPrivileged (
+                new PrivilegedExceptionAction () {
+                    public Object run () throws StorageException {
+                        storage1.commitChanges();
+                        return null;
+                    }
+                }
+            );
+        } catch (PrivilegedActionException ex) {
+            throw new FOStoreDatabaseException(
+                (StorageException)ex.getException());
+        }
+
+    }
+
+    /** Increment the openConnections to allow proper close when the last
+     * connection closes the database.
+     */
+    public synchronized void addConnection() {
+        openConnections++;
+    }
+    
+    /** Decrement the open connections counter and close the database when
+     * it reaches zero.
+     */
+    public synchronized void close() throws FOStoreDatabaseException {
+        if (--openConnections > 0) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("FODB.close: " + getName() +  // NOI18N
+                               " count still " + openConnections); // NOI18N
+            }
+            try {
+                releaseDatabase(this);
+            } catch (InterruptedException ex) {
+                // ignore
+            }
+            return;
+        }
+        // count has reached zero.  Now really close the database.
+        if (logger.isDebugEnabled()) {
+            logger.debug(
+                "FODB.close: count reached zero." + getName()); // NOI18N
+        }
+
+        closeBtreeStorage(storage);
+        databaseMap.remove(getName());
+        pool = null;
+    }
+    
+    public static synchronized void closeDatabase (String dbname)
+        throws FOStoreDatabaseException, InterruptedException {
+
+        Pool pool = (Pool) databaseMap.get(dbname);
+        if (pool == null) {
+            throw new JDOFatalDataStoreException (
+                msg.msg("ERR_CloseDatabase", dbname)); // NOI18N
+        }
+        FOStoreDatabase fodb = (FOStoreDatabase) pool.get();
+        fodb.close();
+    }
+
+    public void rollbackChanges() throws FOStoreDatabaseException {
+        if (logger.isDebugEnabled()) logger.debug("FODB.rollbackChanges"); // NOI18N
+
+        // The btree doesn't *really* rollback.  But closing it and
+        // getting a new one works fine.
+        final String name = storage.getName();
+        closeBtreeStorage(storage);
+        
+        storage = createBtreeStorage(name, false);
+        dbInfo = DBInfo.get(this);
+    }
+
+    static Block createBlock(FOStoreInput in, int length) {
+        return new Block(in, length);
+    }
+    
+    /**
+    * Establishes a mapping in this database from provisional to real
+    * CLIDs.  The mapping lasts as long as the server is running, that is, it
+    * is not durable.
+    * @param pCLID A provisional CLID.
+    * @param rCLID The non-provisional, datastore CLID corresponding to
+    * provCLID.
+    * @exception JDOFatalException Thrown if the given CLID is not provisional.
+    */
+    // If you change this code, please see also method of same name in FOStorePMF.
+    public synchronized void mapProvisionalCLIDToReal(
+        CLID pCLID, CLID rCLID) {
+
+        if (! pCLID.isProvisional()) {
+            throw new JDOFatalException(msg.msg("ERR_CLIDNotProv", pCLID)); // NOI18N
+        }
+        if (null == provisionalCLIDs.get(pCLID)) {
+            provisionalCLIDs.put(pCLID, rCLID);
+        }
+        if (logger.isDebugEnabled()) {
+            logger.debug(
+                "FODB.mapProvCLIDToReal: " + pCLID + " -> " + rCLID); // NOI18N
+        }
+    }
+
+    /**
+    * Provides a datastore CLID corresponding to the given provisional CLID.
+    * @param provCLID A provisional CLID for which there 
+    * @return A non-provisional, datastore CLID corresponding to provCLID, or
+    * null if the given provCLID is not mapped to a datastore CLID.
+    * @exception JDOFatalException Thrown if the given CLID is not provisional.
+    */
+    // If you change this code, see method of same name in FOStorePMF.
+    public CLID getRealCLIDFromProvisional(CLID provCLID) {
+        if (! provCLID.isProvisional()) {
+            throw new JDOFatalException(msg.msg("ERR_CLIDNotProv", provCLID)); // NOI18N
+        }
+        return (CLID)provisionalCLIDs.get(provCLID);
+    }
+
+    /**
+    * Establishes a mapping in this database from provisional to real
+    * OIDs.  The mapping lasts as long as the server is running, that is, it
+    * is not durable.
+    * @param pOID A provisional OID.
+    * @param rOID The non-provisional, datastore OID corresponding to
+    * pOID.
+    * @exception JDOFatalException Thrown if the given OID is not provisional.
+    */
+    // If you change this code, please see also method of same name in FOStorePMF.
+    synchronized void mapProvisionalOIDToReal(
+        OID pOID, OID rOID) {
+
+        if (! pOID.isProvisional()) {
+            throw new JDOFatalException(msg.msg("ERR_OIDNotProv", pOID)); // NOI18N
+        }
+        if (null == provisionalOIDs.get(pOID)) {
+            provisionalOIDs.put(pOID, rOID);
+        }
+    }
+
+    /**
+    * Provides a datastore OID corresponding to the given provisional OID.
+    * @param pOID A provisional OID for which there 
+    * @return A non-provisional, datastore OID corresponding to pOID or null
+    * if the given pOID is not mapped to a datastore OID.
+    * @exception JDOFatalException Thrown if the given OID is not provisional.
+    */
+    // If you change this code, see method of same name in FOStorePMF.
+    OID getRealOIDFromProvisional(OID pOID) {
+        if (! pOID.isProvisional()) {
+            throw new JDOFatalException(msg.msg("ERR_OIDNotProv", pOID)); // NOI18N
+        }
+        return (OID)provisionalOIDs.get(pOID);
+    }
+    
+    private void setPool (Pool pool) {
+        this.pool = pool;
+    }
+
+    /**
+     * Helper method to create a BtreeStorage. This method excutes the
+     * storage operation in a doPrivileged block and handles possible
+     * exceptions.  
+     * @param name name of database, which is used to name the files
+     * @param isNew true if the database is being created
+     * @return new database
+     * @exception FOStoreDatabaseException wraps a StorageException thrown
+     * by the create call.
+     * @exception JDOFatalUserException wraps a possible SecurityException.
+     */
+    private FOStoreBtreeStorage createBtreeStorage(final String name, 
+                                                   final boolean isNew)
+        throws FOStoreDatabaseException, JDOFatalUserException
+    {
+        try {
+            return (FOStoreBtreeStorage) AccessController.doPrivileged (
+                new PrivilegedExceptionAction () {
+                    public Object run () throws StorageException {
+                        return new FOStoreBtreeStorage(name, isNew);
+                    }
+                });
+        } catch (SecurityException ex) {
+            throw new JDOFatalUserException(msg.msg( 
+                "EXC_SecurityExceptionOnCreateBtreeStorage"), ex); //NOI18N
+        } catch (PrivilegedActionException ex) {
+            throw new FOStoreDatabaseException(
+                (StorageException)ex.getException());
+        } 
+    }
+
+    /** 
+     * Helper method to close a BtreeStorage. 
+     * @param storage the database to be closed
+     * @exception FOStoreDatabaseException wraps a StorageException thrown
+     * by the close call.
+     */
+    private void closeBtreeStorage(final FOStoreBtreeStorage storage)
+        throws FOStoreDatabaseException
+    {
+        try {
+            AccessController.doPrivileged (
+                new PrivilegedExceptionAction () {
+                    public Object run () throws StorageException {
+                        storage.shutDown();
+                        storage.close();
+                        return null;
+                    }
+                });
+        } catch (SecurityException ex) {
+            throw new JDOFatalUserException(msg.msg( 
+                "EXC_SecurityExceptionOnCloseBtreeStorage"), ex); //NOI18N
+        } catch (PrivilegedActionException ex) {
+            throw new FOStoreDatabaseException(
+                (StorageException)ex.getException());
+        } 
+    }
+
+    /** 
+     * Helper method to check whether a file exists. This method delegates
+     * to File.exists and handles possible SecurityExceptions.
+     * @param file the file to be checked
+     * @return <code>true</code> if the specified file exists.
+     */ 
+    private boolean existsFile(File file) {
+        try {
+            return file.exists();
+        } catch (SecurityException ex) {
+            throw new JDOFatalUserException(msg.msg(
+                "EXC_CannotReadFile", file.getName()), ex); //NOI18N
+        }
+    }
+
+    /** 
+     * Helper method to delete a file. This method delegates to File.delete
+     * and handles possible SecurityExceptions.
+     * @param file the file to be deleted
+     */
+    private void deleteFile(File file) {
+        try {
+            file.delete();
+        } catch (SecurityException ex) {
+            throw new JDOFatalUserException(msg.msg(
+                "EXC_CannotDeleteFile", file.getName()), ex); //NOI18N
+        }
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreDatabaseException.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreDatabaseException.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreDatabaseException.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreDatabaseException.java Sun May 22 11:40:13 2005
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import org.netbeans.mdr.persistence.StorageException;
+
+/**
+* This provides an insulation layer between BtreeDatabase and FOStore.
+*
+* @author Dave Bristor
+*/
+class FOStoreDatabaseException extends StorageException {
+    private final StorageException ex;
+
+    FOStoreDatabaseException(StorageException ex) {
+        this.ex = ex;
+    }
+
+    public String getLocalizedMessage() {
+        return ex.getLocalizedMessage();
+    }
+
+    public String getMessage() {
+        return ex.getMessage();
+    }
+
+    public void printStackTrace() {
+        ex.printStackTrace();
+    }
+
+    public void printStackTrace(java.io.PrintStream s) {
+        ex.printStackTrace(s);
+    }
+
+    public void printStackTrace(java.io.PrintWriter s) {
+        ex.printStackTrace(s);
+    }
+
+    public String toString() {
+        return ex.toString();
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreExtent.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreExtent.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreExtent.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreExtent.java Sun May 22 11:40:13 2005
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import javax.jdo.Extent;
+import javax.jdo.JDOHelper;
+import javax.jdo.JDOException;
+import javax.jdo.JDOUserException;
+import javax.jdo.PersistenceManager;
+import javax.jdo.Transaction;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.state.StateManagerInternal;
+import org.apache.jdo.util.I18NHelper;
+
+/**
+ * Represents a request to get the extent of a class and possibly its
+ * subclasses.
+ *
+ * @author Dave Bristor
+ */
+//
+// This is client-side code.  It does not need to live in the server.
+//
+/**
+ * This is an in-memory extent.
+ */
+class FOStoreExtent implements Extent {
+private final FOStoreConnector connector;
+private final RequestFactory rf;
+
+    /** Iterators requested by user. */
+    private final HashSet iterators = new HashSet();
+
+    /** Class specified by user. */
+    private final Class cls;
+
+    /** If true, extent includes subclasses of user's class. */
+    private final boolean subclasses;
+
+    /** Persistence manager on which getExtent was invoked by user. */
+    private final PersistenceManagerInternal pm;
+
+    /** I18N support. */
+    private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+    /** Logger */
+    static final Log logger = LogFactory.getFactory().getInstance(
+        "org.apache.jdo.impl.fostore"); // NOI18N
+
+    FOStoreExtent(Class cls, boolean subclasses,
+                  PersistenceManagerInternal pm,
+                  RequestFactory rf,
+                  FOStoreConnector connector) {
+
+         this.cls = cls;
+         this.subclasses = subclasses;
+         this.pm = pm;
+         this.rf = rf;
+         this.connector = connector;
+    }
+
+    //
+    // Implement Extent
+    //
+
+    /**
+     * @see javax.jdo.Extent#iterator
+     */
+    public Iterator iterator() {
+        pm.assertReadAllowed();
+        Iterator rc = new FOStoreExtentIterator(this);
+        iterators.add(rc);
+        return rc;
+    }
+
+    /**
+     * @see javax.jdo.Extent#hasSubclasses
+     */
+    public boolean hasSubclasses() {
+        return subclasses;
+    }
+
+    /**
+     * @see javax.jdo.Extent#getCandidateClass
+     */
+    public Class getCandidateClass() {
+        return cls;
+    }
+
+    /**
+     * @see javax.jdo.Extent#getPersistenceManager
+     */
+    public PersistenceManager getPersistenceManager() {
+        return pm.getCurrentWrapper();
+    }
+
+    /**
+     * @see javax.jdo.Extent#closeAll
+     */
+    public void closeAll() {
+        for (Iterator i = iterators.iterator(); i.hasNext();) {
+            Iterator extentIterator = (Iterator)i.next();
+            if (logger.isDebugEnabled()) {
+                logger.debug("Extent.closeAll: removing " + extentIterator); // NOI18N
+            }
+            i.remove(); // remove first because close also removes it
+            close(extentIterator);
+        }
+    }
+
+    /**
+     * @see javax.jdo.Extent#close
+     */
+    public void close(Iterator it) {
+        if (it instanceof FOStoreExtentIterator) {
+            FOStoreExtentIterator fit = (FOStoreExtentIterator)it;
+            fit.close();
+            if (iterators.contains(fit)) {
+                if (logger.isDebugEnabled()) {
+                    logger.debug("Extent.close: removing " + fit); // NOI18N
+                }
+                // this will be true only if not executing closeAll.
+                iterators.remove(fit);
+            }
+        }
+    }
+
+    /**
+     * Iterates over the elements in a FOStoreExtent.
+     */
+    class FOStoreExtentIterator implements Iterator {
+        /** Instances that have been retrieved from store. */
+        // We have our own copy and do not use those from the enclosing
+        // FOStoreExtent, because we use a GetInstancesRequest to re-fill
+        // the ArrayList if needed.
+        private ArrayList instances;
+        private ArrayList oids;
+        private int maxInstances;
+
+        /** Index into instances. */
+        private int instanceIndex = 0;
+
+        /** Index into oids. */
+        private int oidsIndex = 0;
+
+        /** Index into extent as a whole.*/
+        private int index = 0;
+    
+        /** Size of extent (number of instances + number of oids). */
+        private final int size;
+
+        /** If false, then can get next object, otherwise 
+         * next() always throws NoSuchElementException and 
+         * hasNext() always returns false. */
+        private boolean closed = false;
+
+        private Object nextObject = null;
+
+        FOStoreExtentIterator(FOStoreExtent extent) {
+            try {
+                Message message = connector.getMessage();
+                GetExtentRequest request =
+                    rf.getGetExtentRequest(extent, cls, subclasses, message, pm);
+                request.doRequest();
+                connector.flush();
+                instances = request.getInstances();
+                oids = request.getOIDs();
+                maxInstances = request.getMaxInstances();
+            } catch (IOException ex) {
+                throw new FOStoreFatalIOException(
+                    getClass(), "init", ex); // NOI18N
+            } catch (JDOException ex) {
+                throw ex;
+            } catch (Exception ex) {
+                throw new FOStoreFatalInternalException(
+                    getClass(), "init", ex); // NOI18N
+            }
+    
+            Collection insertedInstances = pm.getInsertedInstances();
+            for (Iterator it = insertedInstances.iterator(); it.hasNext();) {
+                Object o = it.next();
+                Class clz = o.getClass();
+                if (cls.equals(clz) || (subclasses && cls.isAssignableFrom(clz))) {
+                    instances.add(o);
+                }
+            }
+
+            if (logger.isDebugEnabled()) {
+                logger.debug(
+                    "FOStoreExtentIterator.<init>: cls=" + cls.getName() + // NOI18N
+                    ", numInstances=" + instances.size()); // NOI18N
+            }
+
+            this.size = instances.size() + oids.size();
+            if (size == 0) {
+                close();
+            }
+        }
+
+        /**
+         * @see java.util.Iterator#hasNext
+         */
+        public boolean hasNext() {
+            // This code advances to the next not deleted
+            // instance, or until the iterator is closed.
+            // Iterator is closed in getNext() if there
+            // are no more instances available. nextObject
+            // is null at the beginning and after close().
+            while (! closed && (nextObject == null || 
+                                JDOHelper.isDeleted(nextObject))) {
+                getNext();
+            }
+            return (nextObject != null);
+        }
+
+        /**
+         * @see java.util.Iterator#next
+         */
+        public Object next() {
+            if (nextObject == null && !hasNext()) {
+                throw new NoSuchElementException();
+            } 
+
+            Object rc = nextObject;
+            nextObject = null;
+            return rc;
+       }
+
+       /** Get the next instance. Close the iterator if there are 
+        * no more instances available.
+        */
+       private void getNext() {
+            if (index < size) {
+                if (instanceIndex >= instances.size()) {
+                    if (logger.isDebugEnabled()) {
+                        logger.debug(
+                            "FOStoreExtentIterator.next get new instances"); // NOI18N
+                    }
+                    FOStoreStoreManager srm =
+                        (FOStoreStoreManager)pm.getStoreManager();
+                    instances = srm.getInstances(
+                        oids, oidsIndex, maxInstances, pm, cls);
+                    oidsIndex += instances.size();
+                    if (logger.isDebugEnabled()) {
+                        logger.debug(
+                            "FOStoreExtent.next got " + // NOI18N
+                            instances.size() + " instances"); // NOI18N
+                    }
+                    instanceIndex = 0;
+                }
+                nextObject = instances.get(instanceIndex);
+                instanceIndex++;
+                index++;
+
+            } else {
+                close();
+            }
+        }
+
+        /**
+         * Always throws UnsupportedOperationException.
+         */
+        public void remove() {
+            throw new UnsupportedOperationException(
+                msg.msg("EXC_RemoveNotSupported")); // NOI18N
+        }
+
+        /**
+         * Disallow getting further objects from this iterator.
+         */
+        void close() {
+            closed = true;
+            instances = null;
+            index = size;
+            nextObject = null;
+        }
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreFatalIOException.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreFatalIOException.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreFatalIOException.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreFatalIOException.java Sun May 22 11:40:13 2005
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+/**
+* This is an exception which _should_ never be thrown, as it indicates an
+* error in I/O traffic between client and server.  It most likely indicates a
+* bug in the implementation.
+*
+* @author Dave Bristor
+*/
+public class FOStoreFatalIOException extends FOStoreFatalInternalException {
+    /**
+     * @param clz Class in which the exception is thrown.
+     * @param methodName Name of the method from which the exception is
+     * thrown.
+     */
+    FOStoreFatalIOException(Class clz, String methodName, Exception nested) {
+        super(clz, methodName, nested);
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreFatalInternalException.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreFatalInternalException.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreFatalInternalException.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreFatalInternalException.java Sun May 22 11:40:13 2005
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import javax.jdo.JDOFatalInternalException;
+
+/**
+* This is an exception which _should_ never be thrown, as it indicates an
+* error in the implementation, such as a bug that has been found.
+*
+* @author Dave Bristor
+*/
+public class FOStoreFatalInternalException extends JDOFatalInternalException {
+    /**
+     * @param clz Class in which the exception is thrown.
+     * @param methodName Name of the method from which the exception is
+     * thrown.
+     * @param msg The exception message.
+     */
+    FOStoreFatalInternalException(Class clz, String methodName, String msg) {
+        super(clz.getName() + "." + methodName + ": " + msg); // NOI18N
+    }
+
+    /**
+     * @param clz Class in which the exception is thrown.
+     * @param methodName Name of the method from which the exception is
+     * thrown.
+     */
+    FOStoreFatalInternalException(Class clz, String methodName,
+                                  Exception nested) {
+        super(clz.getName() + "." + methodName, // NOI18N
+              new Exception[] {nested}); // NOI18N
+    }
+
+    /**
+     * @param clz Class in which the exception is thrown.
+     * @param methodName Name of the method from which the exception is
+     * thrown.
+     * @param msg The exception message.
+     */
+    FOStoreFatalInternalException(Class clz, String methodName, String msg,
+                                  Exception nested) {
+
+        super(clz.getName() + "." + methodName + ": " + msg, // NOI18N
+              new Exception[] {nested}); // NOI18N
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreInput.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreInput.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreInput.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreInput.java Sun May 22 11:40:13 2005
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.IOException;
+
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+* Extend ByteArrayInputStream so that we can get ahold of the byte array
+* and current position, and can change the current position.
+*
+* @author Dave Bristor
+*/
+class FOStoreInput extends ByteArrayInputStream implements DataInput {
+    private final DataInputStream dis;
+
+    /** I18N support. */
+    private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+    
+    FOStoreInput(byte data[], int off, int len) {
+        super(data, off, len);
+        dis = new DataInputStream(this);
+    }
+
+    byte[] getBuf() {
+        return buf;
+    }
+
+    int getPos() {
+        return pos;
+    }
+
+    void setPos(int pos) {
+        if (pos < 0 || pos > buf.length) {
+            throw new FOStoreFatalInternalException(
+                this.getClass(), "setPos", // NOI18N
+                msg.msg("ERR_InvalidSeekPos", // NOI18N
+                        new Integer(pos), new Integer(buf.length)));
+        }
+        this.pos = pos;
+    }
+
+    // Advance pos by len, but don't break invariant required by
+    // ByteArrayInputStream (see ByteArrayInputStrea.pos's javadoc).
+    void advance(int len) {
+        if (pos + len <= count) {
+            pos += len;
+        } else {
+            pos = count;
+        }
+    }
+
+    //
+    // Implement DataInput
+    //
+
+    public boolean readBoolean() throws IOException {
+        return dis.readBoolean();
+    }
+
+    public byte readByte() throws IOException {
+        return dis.readByte();
+    }
+
+    public char readChar() throws IOException {
+        return dis.readChar();
+    }
+
+    public double readDouble() throws IOException {
+        return dis.readDouble();
+    }
+
+    public float readFloat() throws IOException {
+        return dis.readFloat();
+    }
+
+    public void readFully(byte[] b) throws IOException {
+        dis.readFully(b);
+    }
+
+    public void readFully(byte[] b, int off, int len) throws IOException {
+        dis.readFully(b, off, len);
+    }
+
+    public int readInt() throws IOException {
+        return dis.readInt();
+    }
+
+    public String readLine() throws IOException {
+        return dis.readLine();
+    }
+
+    public long readLong() throws IOException {
+        return dis.readLong();
+    }
+
+    public short readShort() throws IOException {
+        return dis.readShort();
+    }
+
+    public int readUnsignedByte() throws IOException {
+        return dis.readUnsignedByte();
+    }
+
+    public int readUnsignedShort() throws IOException {
+        return dis.readUnsignedShort();
+    }
+
+    public String readUTF() throws IOException {
+        return dis.readUTF();
+    }
+
+    public int skipBytes(int n) throws IOException {
+        return dis.skipBytes(n);
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreLocalConnection.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreLocalConnection.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreLocalConnection.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreLocalConnection.java Sun May 22 11:40:13 2005
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.net.URL;
+import java.net.URLConnection;
+
+import javax.jdo.JDOUserException;
+
+/**
+* Implements the client and server/store connections for the case in which
+* the client and store are running in the same address space.
+*
+* @author Dave Bristor
+*/
+class FOStoreLocalConnection extends FOStoreClientConnectionImpl {
+
+    /** The server that implements the requests
+     */
+    private FOStoreServerConnection server = new FOStoreServerConnectionImpl();
+
+    /**
+    * Provides a connection to the database, using the URL support in 
+    * the superclass.
+    */
+    FOStoreLocalConnection(URL url) {
+        super(url);
+    }
+
+    /**
+     * @see FOStoreClientConnection#getInputFromServer
+     */
+    public DataInput getInputFromServer() throws IOException {
+        return server.getOutputFromServer();
+    }
+    
+    /** Write bytes to the store.  The data is used to construct a FOStoreInput
+     * for the server to use; then the server is called to process the requests.
+     */
+    public void sendToStore(byte[] buffer, int offset, int length) throws IOException {
+        if (logger.isDebugEnabled()) logger.debug("FOLC.wTS: " +  // NOI18N
+                                             (length - offset));
+        server.setClientInput (new FOStoreInput (buffer, offset, length));
+        server.processRequests();
+    }
+ 
+    /** This connects to the data store, and verifies the user name and password..
+     */
+    public void connect() throws IOException {
+        login();
+    }
+    
+    /** Close the database associated with this connection.  This closes the local
+     * server, which causes the remote database to be closed.
+     */
+    public void closeDatabase() throws FOStoreDatabaseException {
+        server.closeDatabase();
+    }
+    
+    /**
+     * @return The <code>path</code> as given.
+     */
+    protected String localizePath(String path) {
+        return path;
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreLoginException.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreLoginException.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreLoginException.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreLoginException.java Sun May 22 11:40:13 2005
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import javax.jdo.JDOFatalUserException;
+
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+* This is an exception which _should_ never be thrown, as it indicates an
+* error in the implementation, such as a bug that has been found.
+*
+* @author Dave Bristor
+*/
+public class FOStoreLoginException extends JDOFatalUserException {
+    /** I18N support. */
+    private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+    /**
+     * @param nested Exception which caused failure
+     * thrown.
+     */
+    FOStoreLoginException(String dbname, String user, Exception nested) {
+        super(msg.msg("EXC_LoginFailed", dbname, user), nested); // NOI18N
+    }
+}
+

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreModel.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreModel.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreModel.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreModel.java Sun May 22 11:40:13 2005
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import javax.jdo.JDOFatalInternalException;
+
+import javax.jdo.spi.PersistenceCapable;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.impl.model.java.runtime.RuntimeJavaModelFactory;
+import org.apache.jdo.model.ModelException;
+import org.apache.jdo.model.jdo.JDOClass;
+import org.apache.jdo.model.jdo.JDOField;
+import org.apache.jdo.model.jdo.JDOIdentityType;
+import org.apache.jdo.model.jdo.JDOModel;
+import org.apache.jdo.pm.PersistenceManagerFactoryInternal;
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.util.I18NHelper;
+
+/**
+* Provides model information required by fostore: mapping between CLID's and
+* the java.lang.Class's.
+*
+* @author Dave Bristor
+*/
+class FOStoreModel {
+    // Maps from java.lang.Class to CLID.
+    private HashMap clids = new HashMap();
+
+    /** Maps from provisional CLID's to java.lang.Class's.  See updateCLID
+    * and getClass.
+    */
+    private HashMap provisionalCLIDs = new HashMap();
+
+    /** Map from jdoClass to an array of FOStoreTranscribers. */
+    private final HashMap transcribers = new HashMap();
+
+    /** Convenience; so that we don't have to getInstance() all the time. */
+    // XXX We may want to rethink how transcribers are accessed.
+    private final FOStoreTranscriberFactory transcriberFactory =
+        FOStoreTranscriberFactory.getInstance();
+
+    /** RuntimeJavaModelFactory. */
+    private static final RuntimeJavaModelFactory javaModelFactory =
+        (RuntimeJavaModelFactory) AccessController.doPrivileged(
+            new PrivilegedAction () {
+                public Object run () {
+                    return RuntimeJavaModelFactory.getInstance();
+                }
+            }
+        );
+
+    /** I18N support. */
+    private static final I18NHelper msg = I18NHelper.getInstance(
+        I18N.NAME, FOStoreModel.class.getClassLoader());
+
+    /** Logger */
+    static final Log logger = LogFactory.getFactory().getInstance(
+        "org.apache.jdo.impl.fostore"); // NOI18N
+
+    /** Constructor */
+    FOStoreModel() { }
+
+    /**
+     * Provides the class id for the given class.
+     * @param cls The class for which the corresponding class id is needed.
+     * @return CLID for the given class, or null if there is no metadata for
+     * that class.
+     */
+   CLID getCLID(Class cls) {
+       // First check if cls has a well-known CLID.  If not, get  metadata for
+       // cls and get the CLID for that.  If still no CLID, create one and map
+       // it in the clids table.
+       CLID rc = CLID.getKnownCLID(cls);
+       if (null == rc) {
+           synchronized(clids) {
+               rc = (CLID)clids.get(cls);
+               if (null == rc) {
+                   rc = CLID.createProvisional();
+                   clids.put(cls, rc);
+                   if (logger.isDebugEnabled()) {
+                       logger.debug(
+                         "FOM.getCLID (new): " + cls + " -> " + rc); // NOI18N
+                   }
+               }
+           }
+       }
+       return rc;
+    }
+
+    /**
+    * Add a mapping from ClassMetaData to CLID.
+    */
+    synchronized void put(Class cls, CLID clid) {
+        clids.put(cls, clid);
+    }
+    
+    /**
+    * Causes the given class mapped to an OID.
+    * @param cls Class to be mapped.
+    * @param type JDOIdentityType as an int.
+    * @param pc PersistenceCapable instance to copy fields from if available. 
+    * @param oid Object Id instance to copy fields from if available. 
+    * @param pm PersistenceManagerInternal that requested the operation.
+    * @param pmf FOStorePMF that requested the operation.
+    * @return ObjectId corresponding to given class.
+    */
+    OID bind(Class cls, int type, PersistenceCapable pc, 
+             Object oid, PersistenceManagerInternal pm, FOStorePMF pmf) {
+        OID rc = null;
+        switch (type) {
+            case JDOIdentityType.APPLICATION:
+                rc = AID.create(cls, pc, oid, pm, pmf);
+                break;
+            case JDOIdentityType.DATASTORE:
+                CLID clid = getCLID(cls);
+                rc = OID.create(clid);
+                break;
+            default:
+                break;
+        }
+        return rc;
+    }
+
+    /**
+     * Changes the class id by which this metadata is known.
+     * @param pCLID The class id by which the class was previously known.
+     * @param rCLID The class id by which the class should be known from now
+     * on in this JVM.
+     */
+    void updateCLID(CLID pCLID, CLID rCLID) {
+        Map.Entry entry = getEntry(pCLID);
+        if (null != entry) {
+            entry.setValue(rCLID);
+            if (null == provisionalCLIDs.get(pCLID)) {
+                Class cls = (Class)entry.getKey();
+                provisionalCLIDs.put(pCLID, cls);
+            }
+        }
+    }
+
+    /**
+    * Return the class corresponding to the given CLID.
+    * @param clid The CLID for which a class is wanted.
+    * @return The java.lang.Class corresponding to the given CLID, or null if
+    * none is found.
+    */
+    Class getClass(CLID clid) {
+        Class rc = null;
+        Map.Entry entry = getEntry(clid);
+        if (null != entry) {
+            rc = (Class)entry.getKey();
+        }
+
+        // It is possible we did not find a mapping.  This can be the case if,
+        // for example, 2 objects are created, and one is stored but not the
+        // other.  The act of storing one will update the clids table via
+        // updateCLID. So we have to look in this other table.
+        if (null == rc && clid.isProvisional()) {
+            rc = (Class)provisionalCLIDs.get(clid);
+        }
+        return rc;
+    }
+
+
+    // Provide the entry which represents the Class - CLID mapping.  While
+    // this may seem time-wise expensive, we don't expect there to be all
+    // *that* many classes (O(100)) per JVM.
+    synchronized Map.Entry getEntry(CLID clid) {
+        Map.Entry rc = null;
+        Set entries = (Set)clids.entrySet();
+        for (Iterator i = entries.iterator(); i.hasNext();) {
+            Map.Entry entry = (Map.Entry)i.next();
+            CLID aCLID = (CLID)entry.getValue();
+            if (clid.equals(aCLID)) {
+                rc = entry;
+                break;
+            }
+        }
+        return rc;
+    }
+
+    //
+    // Provide access to the JDOModel
+    //
+
+    /** @param c Class whose corresponding JDOClass is needed.
+    * @return The JDOClass for the given class.
+    */
+    JDOClass getJDOClass(Class c) {
+        if (logger.isDebugEnabled()) {
+            logger.debug("FOM.getJDOClass for " + c.getName()); // NOI18N
+        }
+        return javaModelFactory.getJavaType(c).getJDOClass();
+    }
+
+    /** Provides a transcriber for the field in the given JDOClass indicated
+    * by fieldNum.
+    * @param c JDOClass for which a transcriber is needed.
+    * @param fieldNum The absolute fieldNumber in the class modeled by
+    * jdoClass that is to be transcribed.
+    * @return a FOStoreTranscriber appropriate for the type of field in the
+    * class modeled by field fieldNum in the class corresponding to
+    * jdoClass.
+    */
+    FOStoreTranscriber getTranscriber(Class c, int fieldNum) {
+        FOStoreTranscriber t[] =
+            (FOStoreTranscriber[])transcribers.get(c);
+        if (null == t) {
+            // Create transcribers for jdoClass
+            JDOClass jdoClass = getJDOClass(c);
+            // Use managed fields here to preserve correct fieldNum's.
+            JDOField fields[] = jdoClass.getManagedFields();
+            int length = fields.length;
+            t = new FOStoreTranscriber[length];
+
+            for (int i = 0; i < length; i++) {
+                if (fields[i].isPersistent()) {
+                    t[i] = (FOStoreTranscriber)transcriberFactory.getTranscriber(
+                        javaModelFactory.getJavaClass(fields[i].getType()))[0];
+                } else {
+                    t[i] = DummyTranscriber.getInstance();
+                }
+            }
+            transcribers.put(c, t);
+        }
+        return t[fieldNum];
+    }
+
+    //
+    // Debug support
+    //
+    
+    void print(Object o) {
+        print (o.getClass());
+    }
+
+    void print(Class c) {
+        JDOModel m = null;
+        try {
+            ClassLoader cl = c.getClassLoader();
+                m = javaModelFactory.getJavaModel(cl).getJDOModel();
+            org.apache.jdo.impl.model.jdo.util.PrintSupport.printJDOModel(m);
+        } catch (Exception ex) {
+            System.out.println("Cannot print model"); // NOI18N
+        }
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreOutput.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreOutput.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreOutput.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreOutput.java Sun May 22 11:40:13 2005
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+* Extend ByteArrayOutputStream so that we can get ahold of the byte array
+* and current position, and can make sure we have enough space to write an
+* object.  We also allow getting and changing the current position.  Also,
+* implement DataOutput so that we can write easily to this output.
+*
+* @author Dave Bristor
+*/
+class FOStoreOutput implements DataOutput {
+    // Once closed, no more writing allowed.
+    private boolean closed = false;
+    
+    private final LocalByteArrayOutputStream stream;
+    private final DataOutputStream dos;
+
+    /** I18N support. */
+    private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+    
+    FOStoreOutput() {
+        stream = new LocalByteArrayOutputStream();
+        dos = new DataOutputStream(stream);
+    }
+
+    /** Close the stream.  The stream can no longer be written.
+     */
+    public void close() {
+        closed = true;
+    }
+    
+    /** Reset the stream.  Discard the current contents, and reset the count
+     * to 0 and the current position to 0.  The current buffer is retained.
+     */
+    public void reset() {
+        stream.reset();
+    }
+
+    // In a simpler world, FOStoreOutput would extend ByteArrayOutputStream
+    // and implement DataOutput.  However.  The creators of the early Java
+    // classes wisely noted that, in ByteArrayOutputStream, the write methods
+    // could not throw IOException, after all, there's no I/O happening.  Of
+    // course, with DataOutput, you never know what's behind the scenes, so
+    // it's write methods *do* throw IOException.  Since we need the
+    // functionality of both, and these are in conflice, we cannot both
+    // extend ByteArrayOutputStream *and* implement DataOutput.  So we
+    // implement DataOutput and delegate to this extension.
+    //
+    class LocalByteArrayOutputStream extends ByteArrayOutputStream {
+        LocalByteArrayOutputStream() {
+            super();
+        }
+
+        byte[] getBuf() {
+            return buf;
+        }
+
+        int getCurrentPosition() {
+            return count;
+        }
+
+        void seek(int pos) {
+            if (pos < 0 || pos > buf.length) {
+                throw new FOStoreFatalInternalException(
+                    this.getClass(), "seek", // NOI18N
+                    msg.msg("ERR_InvalidSeekPos", // NOI18N
+                            new Integer(pos), new Integer(buf.length)));
+            }
+            this.count = pos;
+        }
+    }
+
+    /**
+    * Provides no-copy access to the buffer.
+    * @return The byte array representing this stream.  <em>Not a copy.</em>
+    */
+    byte[] getBuf() {
+        return stream.getBuf();
+    }
+
+    //
+    // A common need of RequestHandlers is to write a nonsense number, which
+    // is later filled in with a count or length (etc.) appropriate to the
+    // reply's acutal data.  These help do that.  Use them instead of
+    // getPos/setPos, if/when you can.
+    //
+    // This is easy to do by hand, but I've burned myself too many times
+    // by being imprecise when doing it that way!
+    //
+
+    /**
+    * Write a nonsense int value at the current position, and return that
+    * position for later use with endStash
+    * @return Position in this output for later use in writing a 'real'
+    * value.
+    * @see #endStash
+    */
+    int beginStash() throws IOException {
+        int rc = getPos();
+        writeInt(0xbadbad10);
+        return rc;
+    }
+
+    /**
+    * Write the given value at the given position, and reset the position to
+    * what it was before the write occurred.
+    * @param value Value to be written
+    * @param pos Position in this output at which value is to be written
+    * @see #beginStash
+    */
+    void endStash(int value, int pos) throws IOException {
+        int savedPos = getPos();
+        setPos(pos);
+        writeInt(value);
+        setPos(savedPos);
+    }
+    
+    /**
+    * Provides the stream's current writing position.
+    * @return The current writing position of the stream.
+    */
+    int getPos() {
+        return stream.getCurrentPosition();
+    }
+
+    /**
+    * Allows for setting the current writing position.
+    * @param pos Position at which future write operations will take
+    * place.
+    */
+    void setPos(int pos) throws IOException {
+        stream.seek(pos);
+    }
+    
+    //
+    // Implement DataOutput by forwarding onto our private DataOutputStream
+    //
+
+    public void write(byte[] b) throws IOException {
+        assertNotClosed();
+        dos.write(b);
+    }
+
+    public void write(int b) throws IOException {
+        assertNotClosed();
+        dos.write(b);
+    }
+
+    public void write(byte[] b, int off, int len) throws IOException {
+        assertNotClosed();
+        dos.write(b, off, len);
+    }
+
+    public void writeBoolean(boolean v) throws IOException {
+        assertNotClosed();
+        dos.writeBoolean(v);
+    }
+
+    public void writeByte(int v) throws IOException {
+        assertNotClosed();
+        dos.writeByte(v);
+    }
+
+    public void writeBytes(String s) throws IOException {
+        assertNotClosed();
+        dos.writeBytes(s);
+    }
+
+    public void writeChar(int v) throws IOException {
+        assertNotClosed();
+        dos.writeChar(v);
+    }
+
+    public void writeChars(String s) throws IOException {
+        assertNotClosed();
+        dos.writeChars(s);
+    }
+
+    public void writeDouble(double v) throws IOException {
+        assertNotClosed();
+        dos.writeDouble(v);
+    }
+
+    public void writeFloat(float v) throws IOException {
+        assertNotClosed();
+        dos.writeFloat(v);
+    }
+
+    public void writeInt(int v) throws IOException {
+        assertNotClosed();
+        dos.writeInt(v);
+    }
+
+    public void writeLong(long v) throws IOException {
+        assertNotClosed();
+        dos.writeLong(v);
+    }
+
+    public void writeShort(int v) throws IOException {
+        assertNotClosed();
+        dos.writeShort(v);
+    }
+
+    public void writeUTF(String str) throws IOException {
+        assertNotClosed();
+        dos.writeUTF(str);
+    }   
+
+    //
+    // Private implementation methods
+    //
+    
+    private void assertNotClosed()  {
+        if (closed) {
+            throw new FOStoreFatalInternalException(
+                getClass(), "assertNotClosed", // NOI18N
+                msg.msg("ERR_Closed")); // NOI18N
+        }
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStorePM.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStorePM.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStorePM.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStorePM.java Sun May 22 11:40:13 2005
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.util.Collection;
+
+import javax.jdo.Extent;
+import javax.jdo.JDOUserException;
+import javax.jdo.Query;
+
+import org.apache.jdo.jdoql.JDOQLQueryFactory;
+
+import org.apache.jdo.impl.pm.PersistenceManagerImpl;
+
+/**
+ * Subclass of {@link #PersistenceManagerImpl} implementing
+ * abstract methods <code>newQuery</code>.
+ *
+ * @author Michael Watzek
+ */
+public class FOStorePM extends PersistenceManagerImpl 
+{
+    /** The JDOQLQueryFactory. */
+    private JDOQLQueryFactory jdoqlQueryFactory;
+
+    /**
+     * Constructs new instance of PersistenceManagerImpl for this
+     * PersistenceManagerFactoryInternal and particular combination of 
+     * username and password.
+     * @param pmf calling PersistenceManagerFactory as
+     * PersistenceManagerFactoryInternal 
+     * @param username user name used for accessing Connector or null if none
+     * is provided.
+     * @param password user password used for accessing Connector or null if 
+     * none is provided.
+     */
+    FOStorePM(FOStorePMF pmf, String username, String password) 
+    {
+        super(pmf, username, password);
+        this.jdoqlQueryFactory = pmf.getJDOQLQueryFactory();
+    }
+    
+    /** Create a new Query with no elements.
+     * @return a new Query instance with no elements.
+     */  
+     public Query newQuery() 
+     {
+         assertIsOpen();
+         return this.jdoqlQueryFactory.newQuery(this);
+     }
+
+     /** Create a new Query using elements from another Query.  The other Query
+     * must have been created by the same JDO implementation.  It might be active
+     * in a different PersistenceManager or might have been serialized and
+     * restored.
+     * @return the new Query
+     * @param compiled another Query from the same JDO implementation
+     */  
+     public Query newQuery(Object compiled) 
+     {
+         assertIsOpen();
+         return this.jdoqlQueryFactory.newQuery(this, compiled);
+     }
+
+     /** Create a new Query using the specified language.
+      * @param language the language of the query parameter
+      * @param query the query, which is of a form determined by the language
+      * @return the new Query
+      */    
+     public Query newQuery(String language, Object query) 
+     {
+         assertIsOpen();
+         if ("javax.jdo.query.JDOQL".equals(language)) //NOI18N
+             return this.jdoqlQueryFactory.newQuery(this, query);
+         throw new JDOUserException(msg.msg(
+                 "EXC_UnsupportedQueryLanguage", language)); // NOI18N
+     }
+     
+     /** Create a new Query specifying the Class of the results.
+     * @param cls the Class of the results
+     * @return the new Query
+     */
+     public Query newQuery(Class cls) 
+     {
+         assertIsOpen();
+         return this.jdoqlQueryFactory.newQuery(this, cls);
+     }
+
+     /** Create a new Query with the candidate Extent; the class is taken
+      * from the Extent.
+      * @return the new Query
+      * @param cln the Extent of candidate instances */  
+     public Query newQuery(Extent cln) 
+     {
+           assertIsOpen();
+           return this.jdoqlQueryFactory.newQuery(this, cln);
+     }
+
+     /** Create a new Query with the Class of the results and candidate 
+      * Collection.
+     * @param cls the Class of results
+     * @param cln the Collection of candidate instances
+     * @return the new Query
+     */
+     public Query newQuery(Class cls, Collection cln) 
+     {
+         assertIsOpen();
+         return this.jdoqlQueryFactory.newQuery(this, cls, cln);
+     }
+
+     /** Create a new Query with the Class of the results and Filter.
+     * @param cls the Class of results
+     * @param filter the Filter for candidate instances
+     * @return the new Query
+     */
+     public Query newQuery(Class cls, String filter) 
+     {
+         assertIsOpen();
+         return this.jdoqlQueryFactory.newQuery(this, cls, filter);
+     }
+
+     /** Create a new Query with the Class of the results, candidate Collection,
+     * and Filter.
+     * @param cls the Class of results
+     * @param cln the Collection of candidate instances
+     * @param filter the Filter for candidate instances
+     * @return the new Query
+     */
+     public Query newQuery(Class cls, Collection cln, String filter) 
+     {
+         assertIsOpen();
+         return this.jdoqlQueryFactory.newQuery(this, cls, cln, filter);
+     }
+
+     /** Create a new Query with the candidate Extent and Filter.
+      * The class is taken from the Extent.
+      * @return the new Query
+      * @param cln the Extent of candidate instances
+      * @param filter the Filter for candidate instances */  
+     public Query newQuery(Extent cln, String filter) 
+     {
+           assertIsOpen();
+           return this.jdoqlQueryFactory.newQuery(this, cln, filter);
+     }
+
+}