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 [7/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/FOStoreStoreManager.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreStoreManager.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreStoreManager.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreStoreManager.java Sun May 22 11:40:13 2005
@@ -0,0 +1,720 @@
+/*
+ * 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.ArrayList;
+import java.util.BitSet;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import javax.jdo.Extent;
+import javax.jdo.JDOException;
+import javax.jdo.JDODataStoreException;
+import javax.jdo.JDOFatalInternalException;
+import javax.jdo.JDOUserException;
+import javax.jdo.JDOFatalUserException;
+import javax.jdo.Transaction;
+import javax.jdo.spi.JDOImplHelper;
+import javax.jdo.spi.PersistenceCapable;
+import javax.jdo.spi.StateManager;
+
+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.query.BasicQueryResult;
+import org.apache.jdo.query.QueryResult;
+import org.apache.jdo.query.QueryResultHelper;
+import org.apache.jdo.model.jdo.JDOClass;
+import org.apache.jdo.model.jdo.JDOIdentityType;
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.state.StateManagerInternal;
+import org.apache.jdo.store.Connector;
+import org.apache.jdo.store.StoreManagerImpl;
+import org.apache.jdo.util.I18NHelper;
+
+//
+// Note the exception handling herein; it is intentional: if we catch a
+// subclass of JDOException, rethrow it as it is "expected" by calling code,
+// but if it is not, then create a subclass of JDOException (as are all
+// FOStore exceptions) and throw that.  In other words, the intent is that
+// only JDOException subclasses be thrown by this class.
+//
+
+/**
+* StoreManager represents the datastore to the rest of the JDO components.
+* It provides the means to write and read instances, to get the extent of
+* classes, and to get the object id for a persistence capable object.
+*
+* @author Dave Bristor
+*/
+class FOStoreStoreManager extends StoreManagerImpl {
+    private final FOStorePMF pmf;
+    private final FOStoreConnector connector;
+    private final RequestFactory rf;
+
+    /** I18N support. */
+    private static final I18NHelper msg = I18NHelper.getInstance(
+        I18N.NAME, FOStoreStoreManager.class.getClassLoader());
+
+    /** Logger */
+    static final Log logger = LogFactory.getFactory().getInstance(
+        "org.apache.jdo.impl.fostore"); // NOI18N
+
+    /** JDOImplHelper instance. */
+    private static final JDOImplHelper jdoImplHelper = 
+        (JDOImplHelper) AccessController.doPrivileged (
+            new PrivilegedAction () {
+                public Object run () {
+                    try {
+                        return JDOImplHelper.getInstance();
+                    }
+                    catch (SecurityException e) {
+                        throw new JDOFatalUserException (msg.msg(
+                            "ERR_Security", e.getMessage()), e); // NOI18N
+                    }
+                }
+            }    
+        );
+
+    /** RuntimeJavaModelFactory. */
+    private static final RuntimeJavaModelFactory javaModelFactory =
+        (RuntimeJavaModelFactory) AccessController.doPrivileged(
+            new PrivilegedAction () {
+                public Object run () {
+                    return RuntimeJavaModelFactory.getInstance();
+                }
+            }
+        );
+
+    FOStoreStoreManager(FOStorePMF pmf) {
+        this.pmf = pmf;
+        this.connector = new FOStoreConnector(pmf);
+        this.rf = pmf.getRequestFactory();
+    }
+    
+    //
+    // Implement org.apache.jdo.store.StoreManager
+    //
+    
+    /**
+    * @see org.apache.jdo.store.StoreManager#getConnector
+    */
+    public Connector getConnector() {
+        return connector;
+    }
+
+    /**
+    * @see org.apache.jdo.store.StoreManager#getConnector(String userid,
+    * String password)
+    */
+    public Connector getConnector(String userid, String password) {
+        throw new JDOUserException("Not yet implemented"); // NOI18N
+    }
+
+    
+    /**
+    * @see org.apache.jdo.store.StoreManager#insert(BitSet, BitSet,
+    * StateManagerInternal)
+    */
+    public synchronized int insert(
+        BitSet loadedFields, BitSet dirtyFields, StateManagerInternal sm) {
+
+        Message message = connector.getMessage();
+        try {
+            if (logger.isDebugEnabled()) {
+                logger.debug("FOSRM.insert"); // NOI18N
+            }
+
+            InsertRequest request = rf.getInsertRequest(sm, message, pmf);
+            request.doRequest();
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                getClass(), "insert", ex); // NOI18N
+        } catch (JDOException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            throw new FOStoreFatalInternalException(
+                getClass(), "insert", ex); // NOI18N
+        }
+        dirtyFields.xor(dirtyFields); // Clear all bits.
+        return StateManagerInternal.FLUSHED_COMPLETE;
+    }
+
+
+    /**
+    * @see org.apache.jdo.store.StoreManager#update(BitSet, BitSet, 
+    * StateManagerInternal)
+    */
+    public synchronized int update(
+        BitSet loadedFields, BitSet dirtyFields, StateManagerInternal sm) {
+
+        Message message = connector.getMessage();
+        try {
+            UpdateRequest request =
+                rf.getUpdateRequest(sm, message, pmf,
+                                    loadedFields, dirtyFields, 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
+        }
+        dirtyFields.xor(dirtyFields); // Clear all bits.
+        return StateManagerInternal.FLUSHED_COMPLETE;
+    }
+
+    
+    /**
+     * @see org.apache.jdo.store.StoreManager#verifyFields(BitSet,
+     * BitSet, StateManagerInternal)
+     */
+    public synchronized int verifyFields(
+        BitSet ignoredFields, BitSet fieldsToVerify, StateManagerInternal sm) {
+
+        if ( ! verify(sm, true, fieldsToVerify)) {
+            throw new JDODataStoreException(
+                msg.msg("EXC_VerifyFields")); // NOI18N
+        }
+        fieldsToVerify.xor(fieldsToVerify); // Clear all bits.
+        return StateManagerInternal.FLUSHED_COMPLETE;
+    }
+
+    // RESOLVE: Marina, do we need this?  @see org.apache.jdo.store.StoreManager#verifyExistence.
+    /**
+     * @see org.apache.jdo.store.StoreManager#verifyExistence
+     */
+//    public boolean verifyExistence(StateManagerInternal sm) {
+//        return verify(sm, false, null, null);
+//    }
+
+    /**
+     * @see org.apache.jdo.store.StoreManager#delete(BitSet, BitSet,
+     * StateManagerInternal)
+     */
+    public synchronized int delete(
+        BitSet loadedFields, BitSet dirtyFields, StateManagerInternal sm) {
+
+        Message message = connector.getMessage();
+        try {
+            DeleteRequest request = rf.getDeleteRequest(sm, message, pmf);
+            request.doRequest();
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                getClass(), "delete", ex); // NOI18N
+        } catch (JDOException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            throw new FOStoreFatalInternalException(
+                getClass(), "delete", ex); // NOI18N
+        }
+        dirtyFields.xor(dirtyFields);
+        return StateManagerInternal.FLUSHED_COMPLETE;
+    }
+
+    /**
+    * @see org.apache.jdo.store.StoreManager#fetch
+    */
+    public synchronized void fetch(StateManagerInternal sm, int fieldNums[]) {
+
+        Message message = connector.getMessage();
+        try {
+            FetchRequest request = rf.getFetchRequest(sm, message, pmf);
+            request.doRequest();
+            connector.flush();
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                getClass(), "fetch", ex); // NOI18N
+        } catch (JDOException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            throw new FOStoreFatalInternalException(
+                getClass(), "fetch", ex); // NOI18N
+        }
+    }
+
+    /**
+    * @see org.apache.jdo.store.StoreManager#getExtent
+    */
+    public synchronized Extent getExtent(Class pcClass, boolean subclasses,
+                            PersistenceManagerInternal pm) {
+
+        FOStoreModel model = pmf.getModel();
+        Message message = connector.getMessage();
+
+        // If the instance's class has PC superclasses, we must make sure
+        // they are activated too.
+        activateClasses(pcClass, message);
+
+        return new FOStoreExtent(pcClass, subclasses, pm, rf, connector);
+    }
+
+    /**
+     * Creates a new object id for the given sm.  Delegates implementation to
+     * #createInternalObjectId(StateManagerInternal sm,Class cls, 
+     * PersistenceManagerInternal pm)
+    * @see org.apache.jdo.store.StoreManager#createObjectId
+    */
+    public synchronized Object createObjectId(StateManagerInternal sm,
+                                              PersistenceManagerInternal pm) {
+        PersistenceCapable obj = sm.getObject();
+        Class cls = obj.getClass();
+        OID rc = createInternalObjectId(sm, obj, null, cls, pm);
+        return rc;
+    }
+
+    /**
+     * Creates a new object id for the given class. Binds metadata for the sm
+     * (i.e., ensures that there is a CLID for instances of the sm's object's
+     * class).  Creates a request in the message that will provide a datastore
+     * oid for the provisional oid which is returned, but does not interact
+     * with the store.
+    * @see org.apache.jdo.store.StoreManager#createObjectId
+    */
+    public synchronized OID createInternalObjectId(StateManagerInternal sm,
+                                   PersistenceCapable pc, Object oid,
+                                   Class cls, PersistenceManagerInternal pm) {
+        FOStoreModel model = pmf.getModel();
+        Message message = connector.getMessage();
+
+        // If the instance's class has PC superclasses, we must make sure
+        // they are activated too.
+        JDOClass jdoClass = model.getJDOClass(cls);
+
+        // Now we can bind class type to the correct OID instance.
+        OID rc = model.bind(cls, jdoClass.getIdentityType(), pc, oid, pm, pmf); 
+
+        activateClasses(cls, message);
+
+        // If the instance's CLID is provisional, we must activate its class.
+        CLID clid = rc.getCLID();
+        if (clid.isProvisional() && ! message.containsCLID(clid)) {
+            activateClass(cls, message);
+            message.addCLID(clid);
+        }
+
+        try {
+            CreateOIDRequest request =
+                rf.getCreateOIDRequest(sm, message, pmf, rc, pm);
+            request.doRequest();
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                getClass(), "createObjectid", ex); // NOI18N
+        }
+        return rc;
+    }
+
+    /**
+     * Provides a datastore object id.
+     * If objectId is not provisional, return it.  Otherwise, see if we have a
+     * corresponding datastore objectId and return that if so.  If neither of
+     * those works out, flush the current message which (we hope) will have a
+     * corresponding CreateObjectIdRequest in it.  Then look as before for a
+     * corresponding datastore objectId in our mapping and return that.  If we
+     * still don't have a correspondance, throw an exception.
+    * @see org.apache.jdo.store.StoreManager#getExternalObjectId(Object oid,
+    * PersistenceCapable pc)
+    */
+    public synchronized Object getExternalObjectId(Object objectId,
+                                                   PersistenceCapable pc) {
+        Object rc = null;
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("FOSRM.getEOID given " + objectId); // NOI18N
+        }
+        OID oid = (OID)objectId;
+        if (oid.isProvisional()) {
+            if (oid.isDataStoreIdentity()) {
+                oid = pmf.getRealOIDFromProvisional(oid);
+
+                if (null == oid) {
+                
+                    // Given objectId is provisional, and we have no mapping.
+                    // Flush so that the CreateObjectId requests that are in
+                    // the current message get written to the store, which
+                    // should cause us to get a datastore oid for the given
+                    // provisional oid.
+                    preFlush();
+                    oid = pmf.getRealOIDFromProvisional((OID)objectId);
+                    if (null == oid) {
+                        throw new JDOUserException(
+                            msg.msg("EXC_UnboundOID"), objectId); // NOI18N
+                    }
+                }
+            } else {
+                // Do flush only:
+                preFlush();
+            }
+        }
+        // Always return a copy
+        rc =  oid.getExternalObjectId(pc);
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("FOSRM.getEOID returning " + rc); // NOI18N
+        }
+        
+        return rc;
+    }
+
+    /**
+    * @see org.apache.jdo.store.StoreManager#copyKeyFieldsFromObjectId
+    */
+    public void copyKeyFieldsFromObjectId(StateManagerInternal sm, 
+                                          Class pcClass) {
+        OID oid = (OID)sm.getInternalObjectId();
+        if (logger.isDebugEnabled()) {
+            logger.debug("FOSRM.copyKeyFieldsFromObjectId: " + oid); // NOI18N
+        }
+        PersistenceManagerInternal pm = sm.getPersistenceManager();
+        FOStoreModel model = pmf.getModel();
+        JDOClass jdoClass = model.getJDOClass(pcClass);
+        oid.copyKeyFieldsToPC(sm, pmf, pcClass, 
+                              jdoClass.getPrimaryKeyFieldNumbers());
+    }
+
+    /**
+    * @see org.apache.jdo.store.StoreManager#hasActualPCClass
+    */
+    public boolean hasActualPCClass(Object objectId) {
+        boolean rc = false;
+        if (objectId instanceof OID) {
+            rc = ((OID)objectId).isDataStoreIdentity();
+        }
+        if (logger.isDebugEnabled()) {
+            logger.debug("FOSRM.hasActualPCClass: " + rc); // NOI18N
+        }
+        return rc;
+    }
+
+    /**
+    * @see org.apache.jdo.store.StoreManager#getInternalObjectId
+    */
+    public synchronized Object getInternalObjectId(Object objectId,
+                                                   PersistenceManagerInternal pm) {
+        OID rc = null;
+        if (logger.isDebugEnabled()) {
+            logger.debug("FOSRM.getInternalObjectId: " + objectId); // NOI18N
+        }
+        if (objectId instanceof OID) {
+            rc = ((OID)objectId).copy();
+        } else {
+            Class cls = getPCClassForOid(objectId, pm);
+            rc = createInternalObjectId(null, null, objectId, cls, pm);
+            if (logger.isDebugEnabled()) {
+                logger.debug("FOSRM.getInternalObjectId: got=" + rc); // NOI18N
+            }
+        }
+        return rc;
+    }
+
+    /**
+    * @see org.apache.jdo.store.StoreManager#getPCClassForOid
+    */
+    public synchronized Class getPCClassForOid(Object objectId,
+                                             PersistenceManagerInternal pm) {
+        Class rc = null;
+        Message message = connector.getMessage();
+        try {
+            if (logger.isDebugEnabled()) {
+                logger.debug("FOSRM.getPCClassForOid: " + 
+                               objectId.getClass().getName() + objectId); // NOI18N
+            }
+            if (!(objectId instanceof OID)) {
+                Class cls = objectId.getClass();
+                rc = pm.loadPCClassForObjectIdClass(cls);
+            } else {
+                OID oid = (OID)objectId;
+                CLID clid = oid.getCLID();
+
+                FOStoreModel model = pmf.getModel();
+                rc = model.getClass(clid);
+
+                if (null == rc) {
+                    if (logger.isDebugEnabled()) {
+                        logger.debug(
+                            "FOSRM.getPCClassForOid: asking store for CLID: " +
+                            clid); // NOI18N
+                    }
+                    // The clid is not known in this JVM, but it might be known
+                    // in the store.  Try to get it.
+                    GetClassRequest request =
+                        rf.getGetClassRequest(clid, message, pmf, pm);
+                    try {
+                        request.doRequest();
+                        connector.flush();
+                        rc = request.getClassForCLID();
+                    } catch (IOException ex) {
+                        throw new FOStoreFatalIOException(
+                            getClass(), "getPCClassForOid", ex); // NOI18N
+                    }
+                }
+            }
+            if (logger.isDebugEnabled()) {
+                logger.debug("FOSRM.getPCClassForOid: got " + rc); // NOI18N
+            }
+        } catch (ClassCastException ex) {
+            throw new JDOUserException(
+                msg.msg("EXC_NotOID"), ex, objectId); // NOI18N
+        } catch (ClassNotFoundException ex) {
+            throw new JDOUserException(
+                msg.msg("EXC_NotOID"), ex, objectId); // NOI18N
+        } catch (JDOException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            throw new FOStoreFatalInternalException(
+                getClass(), "getPCClassForOid", ex); // NOI18N
+        }
+        return rc;
+    }
+
+    /** 
+     * This method returns an object id instance corresponding to the Class 
+     * and String arguments. The String argument might have been the 
+     * result of executing toString on an object id instance. 
+     * @param pcClass the Class of the persistence-capable instance
+     * @param str the String form of the object id
+     * @return an instance of the object identity class
+     */
+    public Object newObjectIdInstance (Class pcClass, String str) {
+        Object rc = null;
+        FOStoreModel model = pmf.getModel();
+        JDOClass jdoClass = model.getJDOClass(pcClass);
+        switch (jdoClass.getIdentityType()) {
+          case JDOIdentityType.APPLICATION:
+            //No need to create an AID here - it will not be used.
+            rc = jdoImplHelper.newObjectIdInstance(pcClass, str);
+            break;
+          case JDOIdentityType.DATASTORE:
+            rc = new OID(str);
+            break;
+          default:
+            break;
+        }
+        return rc;
+    }
+
+    /**
+     * Returns a QueryResult instance which is then returned as the result of 
+     * Query.execute(...). This method allows support for datastore specific 
+     * query execution strategies, since each StoreManager can have its own
+     * implementation of the QueryResult interface. 
+     * For now fostore uses the non optimized BasicQueryResult as QueryResult
+     * implemenatation.
+     * @param qrh the helper providing the query tree, the candidates 
+     * and the actual parameters.
+     * @return a datastore specific query result instance
+     */
+    public QueryResult newQueryResult(QueryResultHelper qrh) {
+        return new BasicQueryResult(qrh);
+    }
+
+    //
+    // Used within FOStore
+    //
+
+    /**
+     * Activates this class and all supeclasses.
+     */  
+    private void activateClasses(Class cls, Message message) {
+        FOStoreModel model = pmf.getModel();
+        // If the instance's class has PC superclasses, we must make sure
+        // they are activated too.
+        JDOClass jdoClass = model.getJDOClass(cls);
+        JDOClass jdoSuper = jdoClass.getPersistenceCapableSuperclass();
+        if (null != jdoSuper) {
+            ArrayList javaSupers = new ArrayList();
+            while (null != jdoSuper) {
+                Class javaSuper = javaModelFactory.
+                    getJavaClass(jdoSuper.getJavaType());
+                javaSupers.add(javaSuper);
+                jdoSuper = jdoSuper.getPersistenceCapableSuperclass();
+            }
+
+            // Activate the superclasses in order from Object on down, so
+            // that the store can recognize subclasses.
+            int size = javaSupers.size();
+            for (int i = size - 1; i >= 0; i--) {
+                Class javaSuper = (Class)javaSupers.get(i);                
+                CLID clidSuper = model.getCLID(javaSuper);
+                if (clidSuper.isProvisional() && 
+                    ! message.containsCLID(clidSuper)) {
+                    activateClass(javaSuper, message);
+                    message.addCLID(clidSuper);
+                }
+            }
+        }
+
+    }
+    /**
+     * Writes a request to activate the given state manager's class
+     */
+    private void activateClass(Class cls, Message message) {
+        ActivateClassRequest request =
+            rf.getActivateClassRequest(cls, message, pmf);
+        try {
+            request.doRequest();
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                getClass(), "activateClass", ex); // NOI18N
+        }
+    }
+
+    /**
+    * Dumps information about the store. The provided information
+    * depends on the <code>option</code> parameter.  Currently,
+    * there are the following options supported: 
+    * <ul>
+    * <li>DBInfo: Provide information about all classes stored in the
+    * database.</li>
+    * <li>MetaData: Provide metadata information about the class
+    * <code>name</code>.</li>
+    * </ul>
+    * @param option Dump option, specifies the kind of information.
+    * @param name Optional fully qualified classname.
+    * @see org.apache.jdo.impl.fostore.DumpOption
+    */
+    public String dump(DumpOption option, String name) {
+        Message message = connector.getMessage();
+        try {
+            DumpRequest request =
+                rf.getDumpRequest(option, name, message, pmf);
+            request.doRequest();
+            connector.flush();
+            return request.getDump();
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                getClass(), "dump", ex); // NOI18N
+        } catch (JDOException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            throw new FOStoreFatalInternalException(
+                getClass(), "dump", ex); // NOI18N
+        }
+    }
+
+    /**
+     * Get instances for oids
+     * @param oids List of oids
+     * @param start Starting index within <code>oids</code> of oids whose
+     * instances are to be returned.
+     * @param numInstances Number of instances to return.
+     * @param pm PersistenceManagerInternal on whose behalf the instances are
+     * being obtained.
+     * @param cls Candidate Class for which instances are being obtained.
+     * @return ArrayList of instances corresponding to
+     * <code>numInstances</code> of oids in the <code>oids</code> parameter,
+     * starting at <code>start</code>.
+     */
+    synchronized ArrayList getInstances(
+        ArrayList oids, int start, int numInstances,
+        PersistenceManagerInternal pm, Class cls) {
+
+        ArrayList rc = null;
+        Message message = connector.getMessage();
+        try {
+            GetInstancesRequest request =
+                rf.getGetInstancesRequest(oids, start, numInstances,
+                                          message, pm, cls);
+            request.doRequest();
+            connector.flush();
+            rc = request.getInstances();
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                getClass(), "getInstances", ex); // NOI18N
+        } catch (JDOException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            throw new FOStoreFatalInternalException(
+                getClass(), "getInstances", ex); // NOI18N
+        }
+        return rc;
+    }
+
+    //
+    // Implementation detail
+    //
+    
+    /**
+     * Verifies existence or values of a state manager's object in the
+     * database.
+     * @param sm The state manager whose object is to be verified.
+     * @param verifyFields If true, verify values of object, otherwise verify
+     * only existence (and ignore remaining parameters).
+     * @param fieldsToVerify Set of fields to be verified against those in the
+     * database.
+     * @return true if verify was successful (either by existence of value
+     * matching as per verifyFields).
+     */
+    private boolean verify(StateManagerInternal sm,
+                           boolean verifyFields, BitSet fieldsToVerify) {
+
+        boolean rc = false;
+        Message message = connector.getMessage();
+        try {
+            VerifyRequest request =
+                rf.getVerifyRequest(sm, message, pmf,
+                                    verifyFields, fieldsToVerify);
+            request.doRequest();
+            connector.flush();
+            rc = request.getVerified();
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                getClass(), "verify", ex); // NOI18N
+        } catch (JDOException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            throw new FOStoreFatalInternalException(
+                getClass(), "verify", ex); // NOI18N
+        }
+        return rc; //success
+    }
+
+    /**
+     * Write a CommitRequest and flush the connector, to cause all
+     * CreateOid and ActivateClass requests to be committed in the
+     * database *before* any inserts, updates, or deletes.
+     */
+    protected void preFlush() {
+        Message message = connector.getMessage();
+        CommitRequest request = rf.getCommitRequest(message, pmf);
+        if (logger.isDebugEnabled()) {
+            logger.debug("FOSRM.preFlush"); // NOI18N
+        }
+        try {
+            request.setOkToReleaseDatabase(false);
+            request.doRequest();
+            connector.flush();
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                getClass(), "flush", ex); // NOI18N
+        } catch (JDOException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            throw new FOStoreFatalInternalException(
+                getClass(), "flush", ex); // NOI18N
+        }
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreTranscriber.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreTranscriber.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreTranscriber.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreTranscriber.java Sun May 22 11:40:13 2005
@@ -0,0 +1,193 @@
+/*
+ * 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.DataOutput;
+import java.io.IOException;
+
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.store.Transcriber;
+
+
+//
+// A note on Strings and Objects
+//
+// The JDO spec calls out special treatment for primitives and Strings,
+// lumping everything else into the category "Object".  For example,
+// StateManager has providedStringField().  So, one would think this singling
+// out of String as a "primitive Object" would continue here.
+//
+// We have not done so.  The reason is Collections.  Primitives are never
+// elements of Collections, only Objects.  Strings are Objects.  To treat
+// them as primitives would require special treatment in each of the
+// collection transcribers.  Rather than do that, we treat Strings as
+// Objects.  Eventually, Strings get the same treatment as other immutable
+// types such as Integer; see ImmutableStringTranscriber.
+//
+
+/**
+* FOStoreTranscriber contains methods to transcribe each primitive type,
+* but they all throw AbstractMethodError.  Subclasses do the actual
+* work, implementing methods for one and only one type of data.
+*
+* @author Dave Bristor
+*/
+abstract class FOStoreTranscriber implements Transcriber {
+    // See ObjectTranscriber's description of getInstance() method.
+    static final ObjectTranscriber objectTranscriber =
+        new ObjectTranscriber();
+
+    //
+    // Transcriber methods.  All are quasi-abstract: they are intended to be
+    // overridden.
+    //
+    
+    void storeBoolean(boolean value, DataOutput out) throws IOException {
+        throw new FOStoreAbstractMethodException(
+            getClass().getName() + ".storeBoolean"); // NOI18N
+    }
+
+    boolean fetchBoolean(DataInput in) throws IOException {
+        throw new FOStoreAbstractMethodException(
+            getClass().getName() + ".fetchBoolean"); // NOI18N
+    }
+
+    
+    void storeChar(char value, DataOutput out) throws IOException {
+        throw new FOStoreAbstractMethodException(
+            getClass().getName() + ".storeChar"); // NOI18N
+    }
+
+    char fetchChar(DataInput in) throws IOException {
+        throw new FOStoreAbstractMethodException(
+            getClass().getName() + ".fetchChar"); // NOI18N
+    }
+
+    
+    void storeByte(byte value, DataOutput out) throws IOException {
+        throw new FOStoreAbstractMethodException(
+            getClass().getName() + ".storeByte"); // NOI18N
+    }
+
+    byte fetchByte(DataInput in) throws IOException {
+        throw new FOStoreAbstractMethodException(
+            getClass().getName() + ".fetchByte"); // NOI18N
+    }
+
+    
+    void storeShort(short value, DataOutput out) throws IOException {
+        throw new FOStoreAbstractMethodException(
+            getClass().getName() + ".storeShort"); // NOI18N
+    }
+
+    short fetchShort(DataInput in) throws IOException {
+        throw new FOStoreAbstractMethodException(
+            getClass().getName() + ".fetchShort"); // NOI18N
+    }
+
+    
+    void storeInt(int value, DataOutput out) throws IOException {
+        throw new FOStoreAbstractMethodException(
+            getClass().getName() + ".storeInt"); // NOI18N
+    }
+
+    int fetchInt(DataInput in) throws IOException {
+        throw new FOStoreAbstractMethodException(
+            getClass().getName() + ".fetchInt"); // NOI18N
+    }
+
+    
+    void storeLong(long value, DataOutput out) throws IOException {
+        throw new FOStoreAbstractMethodException(
+            getClass().getName() + ".storeLong"); // NOI18N
+    }
+
+    long fetchLong(DataInput in) throws IOException {
+        throw new FOStoreAbstractMethodException(
+            getClass().getName() + ".fetchLong"); // NOI18N
+    }
+
+    
+    void storeFloat(float value, DataOutput out) throws IOException {
+        throw new FOStoreAbstractMethodException(
+            getClass().getName() + ".storeFloat"); // NOI18N
+    }
+
+    float fetchFloat(DataInput in) throws IOException {
+        throw new FOStoreAbstractMethodException(
+            getClass().getName() + ".fetchFloat"); // NOI18N
+    }
+
+    
+    void storeDouble(double value, DataOutput out) throws IOException {
+        throw new FOStoreAbstractMethodException(getClass().getName() +
+                                        ".storeDouble"); // NOI18N
+    }
+
+    double fetchDouble(DataInput in) throws IOException {
+        throw new FOStoreAbstractMethodException(
+            getClass().getName() + ".fetchDouble"); // NOI18N
+    }
+
+    void skip(DataInput in) throws IOException {
+        throw new FOStoreAbstractMethodException(
+            getClass().getName() + ".skip"); // NOI18N
+    }
+
+
+    //
+    // Note that the signatures and visibilty of the Object-related
+    // transcribing methods differ from the above.
+    //
+    // The publicly visible storeObject requires a PersistenceManagerInternal
+    // parameter, so that we can get its StoreManager and an OIDs
+    // corresponding to a Java objects.
+    //
+    // The signature of fetchObject takes Object and int parameters so that
+    // we can support SCO's, which must be created with an owner and field
+    // number.  It takes a PM so that it can create an object from an OID.
+    //
+
+    int[] storeObject(Object value, FOStoreOutput out,
+                      PersistenceManagerInternal pm) throws IOException {
+                          throw new FOStoreAbstractMethodException(
+                              getClass().getName() + ".storeObject"); // NOI18N
+    }
+
+    protected int[] storeObject(Object value, FOStoreOutput out)
+        throws IOException {
+
+            throw new FOStoreAbstractMethodException(
+                getClass().getName() + ".storeObject"); // NOI18N
+    }
+
+    Object fetchObject(DataInput in, Object owner, int fieldNum,
+                       PersistenceManagerInternal pm)
+        throws IOException, Exception {
+
+            throw new FOStoreAbstractMethodException(
+                getClass().getName() + ".fetchObject"); // NOI18N
+    }
+
+    protected Object fetchObject(DataInput in, Object owner, int fieldNum)
+        throws IOException, Exception {
+
+            throw new FOStoreAbstractMethodException(
+                getClass().getName() + ".fetchObject"); // NOI18N
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreTranscriberFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreTranscriberFactory.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreTranscriberFactory.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreTranscriberFactory.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.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.HashMap;
+
+import javax.jdo.JDOException;
+
+import org.apache.jdo.store.Transcriber;
+import org.apache.jdo.store.TranscriberFactory;
+
+
+/**
+* Provides Transcriber instances for FOStore.  Note that only one instance of
+* any kind of transcriber is ever created.
+*
+* @author Dave Bristor
+*/
+class FOStoreTranscriberFactory implements TranscriberFactory {
+    // Singleton
+    private static FOStoreTranscriberFactory instance;
+
+    private static HashMap transcribers = new HashMap(10);
+
+    private FOStoreTranscriberFactory() {
+        transcribers.put(boolean.class,
+            new Transcriber[] { BooleanTranscriber.getInstance()});
+        transcribers.put(char.class,
+            new Transcriber[] { CharTranscriber.getInstance()});
+        transcribers.put(byte.class,
+            new Transcriber[] { ByteTranscriber.getInstance()});
+        transcribers.put(short.class,
+            new Transcriber[] { ShortTranscriber.getInstance()});
+        transcribers.put(int.class,
+            new Transcriber[] { IntTranscriber.getInstance()});
+        transcribers.put(long.class,
+            new Transcriber[] { LongTranscriber.getInstance()});
+        transcribers.put(float.class,
+            new Transcriber[] { FloatTranscriber.getInstance()});
+        transcribers.put(double.class,
+            new Transcriber[] { DoubleTranscriber.getInstance()});
+        transcribers.put(Object.class,
+            new Transcriber[] { ObjectTranscriber.getInstance()});
+    }
+    
+    static FOStoreTranscriberFactory getInstance() {
+        if (null == instance) {
+            instance = new FOStoreTranscriberFactory();
+        }
+        return instance;
+    }
+
+    /**
+    * Provides a Transcriber for the given class.  The result is an array, as
+    * defined by the interface, but the return here always contains only one
+    * Transcriber.
+    * @param cls Class for which a Transcriber is needed.
+    * @return An array of transcribers; array will contain only one
+    * Transcriber.
+    */
+    public Transcriber[] getTranscriber(Class cls) {
+        Transcriber rc[] = null;
+            if (cls != null) {
+                rc = (Transcriber[])transcribers.get(cls);
+                if (null == rc) {	// cls not of a primitive
+                    rc = (Transcriber[])transcribers.get(Object.class);
+                }
+            }
+        return rc;
+    }
+}
+
+    

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreURLStreamHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreURLStreamHandler.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreURLStreamHandler.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreURLStreamHandler.java Sun May 22 11:40:13 2005
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+/*
+ * FOStoreURLStreamHandler.java
+ *
+ * Created on June 7, 2001, 7:11 PM
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.net.URLStreamHandler;
+import java.net.URLConnection;
+import java.io.IOException;
+
+/**
+ * Creates connections to databases.
+ * @author  Craig Russell
+ * @version 1.0
+ */
+class FOStoreURLStreamHandler extends URLStreamHandler {
+    
+    static FOStoreURLStreamHandler sh = new FOStoreURLStreamHandler();
+    
+    static FOStoreURLStreamHandler getInstance() {
+        return sh;
+    }
+
+    /** Creates new FOStoreURLStreamHandler */
+    public FOStoreURLStreamHandler() {
+    }
+    
+    protected URLConnection openConnection(java.net.URL url) 
+            throws IOException {
+        if (url.getHost().length() == 0) {
+            // local connection
+            return new FOStoreLocalConnection(url);
+        } else {
+            // remote connection
+            return new FOStoreRemoteConnection(url);
+        }
+    }
+
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreUnsupportedException.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreUnsupportedException.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreUnsupportedException.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreUnsupportedException.java Sun May 22 11:40:13 2005
@@ -0,0 +1,34 @@
+/*
+ * 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.JDOFatalException;
+
+/**
+* This exception means that a FOStore doesn't have support for what is being
+* requested.  This differs from  JDOUnsupportedException, which indicates that
+* an optional feature has not been implemented.  This is used, for example, to
+* indicate that storing of a particular type (e.g. an array of non-PC objects)
+* is not supported.
+*
+* @author Dave Bristor
+*/
+class FOStoreUnsupportedException extends JDOFatalException {
+    FOStoreUnsupportedException(String msg) {
+        super(msg);
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FetchHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FetchHandler.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FetchHandler.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FetchHandler.java Sun May 22 11:40:13 2005
@@ -0,0 +1,143 @@
+/*
+ * 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.DataOutput;
+import java.io.IOException;
+import java.util.Iterator;
+
+import javax.jdo.JDOUserException;
+
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+* Process fetch requests.
+*
+* @author Dave Bristor
+*/
+//
+// This is server-side code.  It does not need to live in the client.
+//
+class FetchHandler extends RequestHandler {
+
+    /** I18N support. */
+    private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+    private FetchHandler(Reply reply, int length,
+                         FOStoreServerConnection con) {
+
+        super(reply, length, con);
+    }
+    
+    public static final HandlerFactory factory =
+        new HandlerFactory() {
+                public RequestHandler getHandler(Reply reply, int length,
+                                             FOStoreServerConnection con) {
+                return new FetchHandler(reply, length, con);
+            }};
+
+    RequestFinisher handleRequest()
+        throws IOException, FOStoreDatabaseException {
+
+        // XXX TBD Handle numFields and fieldNums.  For now, we're expecting
+        // only an OID, and we return all field values.
+
+        DataInput in = con.getInputFromClient();
+        boolean knownclass = in.readBoolean();
+        OID oid = OID.read(in);
+        CLID clid = oid.getCLID();
+
+        FOStoreDatabase fodb = con.getDatabase();
+        Block block = null;
+        try {
+            block = (Block)fodb.getIfExists(oid);
+            if (null == block) {
+                if (logger.isDebugEnabled()) {
+                    logger.debug("FR.reply: nonexistent: " + oid); // NOI18N
+                }
+
+                if (knownclass == false) {
+                    long uid = oid.getUID();
+                    OID tempOid = null;
+                    if (clid.isProvisional()) {
+                        // Retry with the known class id.
+                        if (logger.isDebugEnabled()) {
+                            logger.debug("FH.hR: replace provisional clid..."); // NOI18N
+                        }
+                        clid = fodb.getRealCLIDFromProvisional(clid);
+                        tempOid = OID.create(clid, uid);
+                        block = (Block)fodb.getIfExists(tempOid);
+                    }
+                    if (null == block) {
+                        // Still not found. Now test subclasses.
+
+                        if (logger.isDebugEnabled()) {
+                            logger.debug("FH.hR: test subclassess..."); // NOI18N
+                        }
+
+                        OID ssOID = DBInfo.getSubclassSetOID(clid);
+                        SubclassSet ss = (SubclassSet)fodb.getIfExists(ssOID);
+                        if (logger.isDebugEnabled()) {
+                           logger.debug("FH.hR: subclassOID: " + ssOID); // NOI18N
+                        }
+                        if (null != ss) {
+                            if (logger.isDebugEnabled()) {
+                                logger.debug("FH.hR: SubclassSet exists for : " + clid); // NOI18N
+                            }
+                            for (Iterator i = ss.iterator(); i.hasNext();) {
+                                CLID subCLID = (CLID)i.next();
+                                tempOid = OID.create(subCLID, uid);
+                                if (logger.isDebugEnabled()) {
+                                    logger.debug("FH.hR: looking for : " + tempOid); // NOI18N
+                                }
+                                block = (Block)fodb.getIfExists(tempOid);
+                                if (block != null) {
+                                    if (logger.isDebugEnabled()) {
+                                        logger.debug("FH.hR: exists: " + tempOid); // NOI18N
+                                    }
+
+                                    clid = subCLID;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (null == block) {
+                reply.setStatus(
+                    Status.WARN,
+                    msg.msg("EXC_DoesNotExist", oid.toString())); // NOI18N
+            } else {
+                if (logger.isTraceEnabled()) {
+                    logger.trace("FR.reply data:"); // NOI18N
+                    block.dump();
+                }
+                reply.write(block.getData());
+                reply.writeCLID(clid);
+                reply.setStatus(Status.OK);
+            }
+        } catch (FOStoreDatabaseException ex) {
+            reply.setStatus(Status.ERROR, ex);
+        }
+
+        return null;
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FetchRequest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FetchRequest.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FetchRequest.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FetchRequest.java Sun May 22 11:40:13 2005
@@ -0,0 +1,137 @@
+/*
+ * 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 javax.jdo.JDOUserException;
+import javax.jdo.JDOObjectNotFoundException;
+
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.state.StateManagerInternal;
+
+
+/**
+ * Represents a request to read the values of one or more fields for a
+ * persistent object from the store.
+ *
+ *
+ * @author Dave Bristor
+ */
+//
+// This is client-side code.  It does not need to live in the server.
+//
+class FetchRequest extends AbstractRequest implements FieldRequest {
+    private final OID oid;
+    private final Object owner;
+    private final PersistenceManagerInternal pm;
+
+    FetchRequest(StateManagerInternal sm, Message m, FOStorePMF pmf) {
+        super(sm, m, pmf);
+        
+        this.oid = (OID)sm.getInternalObjectId();
+        this.owner = sm; // Owner will be set to StateManagerInternal
+        this.pm =  (PersistenceManagerInternal)sm.getPersistenceManager();
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("FetchRequest: " + oid); // NOI18N
+        }
+    }
+
+    //
+    // Methods from AbstractRequest
+    //
+
+    protected void doRequestBody() throws IOException {
+        //
+        // The format of this request is (aside from the request header):
+        //
+        // oid: OID
+        // numFields: int
+        // fieldNum: int...
+        //
+
+        out.writeBoolean(pm.getStoreManager().hasActualPCClass(oid));
+        oid.write(out);
+
+        // XXX TBD Make use of the fieldNums (right now we fetch all
+        // fields).  This will entail writing more output as per above.
+    }
+
+    
+    //
+    // Methods from Request
+    //
+
+    public void handleReply(Status status, DataInput in, int length)
+    throws IOException {
+
+        //
+        // The format of this reply is
+        //
+        // className: String
+        // fieldsLength: int
+        // fieldValue: Object...
+        // numPairs: int
+        // CLID, classname pairs...
+        //
+        // The value types are as per the metadata, and are provided in the
+        // same order as that in which they were requested.
+        //
+
+        byte data[] = new byte[length];
+        if (logger.isDebugEnabled()) {
+            logger.debug("FR.hR: reading " + length + " bytes"); // NOI18N
+        }
+        in.readFully(data);
+
+        if (status.equals(Status.WARN)) {
+            String message = in.readUTF();
+            throw new JDOObjectNotFoundException(message);
+        }
+
+        ClassLoader loader = sm.getPCClass().getClassLoader();
+        
+        FieldFetcher ff =
+            new FieldFetcher(new FOStoreInput(data, 0, length),
+                             pmf.getModel(),
+                             pm,
+                             loader);
+        ff.fetch(sm, oid);
+    }
+
+    
+    //
+    // Implement FieldRequest
+    //
+    
+    /**
+    * Determines which fields (at least) will be read from the store.  We say
+    * 'at least' because while we guarantee that the specified fields will be
+    * read, other fields may be read; this is implementation dependent.
+    * @param fieldNums Numbers of the fields which are to be read from the
+    * store.
+    */
+    public void setFieldNums(int fieldNums[]) { }
+
+    /**
+      * Adds to the set of fields that are to be manipulated.
+      * @param fieldNum Number of the field to be manipulated.
+      */
+    public void addFieldNum(int fieldNum) { }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FieldFetcher.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FieldFetcher.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FieldFetcher.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FieldFetcher.java Sun May 22 11:40:13 2005
@@ -0,0 +1,474 @@
+/*
+ * 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 javax.jdo.JDOFatalUserException;
+import javax.jdo.JDOUserException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.model.jdo.JDOClass;
+import org.apache.jdo.model.jdo.JDOField;
+import org.apache.jdo.model.jdo.PersistenceModifier;
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.state.StateManagerInternal;
+import org.apache.jdo.util.I18NHelper;
+
+/**
+* Extend AbstractFieldManager overriding only fetchABCField methods
+*
+* @author Dave Bristor
+*/
+class FieldFetcher extends AbstractFieldManager {
+    /** Read values from here. */
+    private final FOStoreInput fin;
+
+    /** PM on whose behalf we read */
+    private final PersistenceManagerInternal pm;
+
+    private final FOStoreModel model;
+
+    /** ClassLoader to use for loading the class of the instance. */
+    private final ClassLoader candidateLoader;
+
+    /** Class of instance being fetched. */
+    private Class cls;
+
+    //
+    // One of the follwing 2 fields, sm and oid, will be set at an entry to
+    // this object.
+    //
+    
+    // StateManger for which we're reading data.
+    private StateManagerInternal sm = null;
+
+    // OID for which we're reading data.
+    private OID oid = null;
+
+    // OID provided for the request.
+    private OID oldOID = null;
+
+    // Last read field number
+    private int currNum = 0;
+
+    // Flag that enables actual field skip.
+    // If set to false only currNum is ignored.
+    private boolean skip = true;
+
+    /** 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
+    
+    FieldFetcher(FOStoreInput fin,
+                 FOStoreModel model,
+                 PersistenceManagerInternal pm,
+                 ClassLoader candidateLoader) {
+
+        this.fin = fin;
+        this.model = model;
+        this.pm = pm;
+        this.candidateLoader = candidateLoader;
+        this.skip = true;
+    }
+
+    /** Called by AID when PK fields are written sequentially
+     * independent of their actual field numbers.
+     */
+    FieldFetcher(FOStoreInput fin,
+                 FOStoreModel model,
+                 PersistenceManagerInternal pm,
+                 ClassLoader candidateLoader,
+                 boolean skip) {
+
+        this.fin = fin;
+        this.model = model;
+        this.pm = pm;
+        this.candidateLoader = candidateLoader;
+        this.skip = skip;
+    }
+
+    //
+    // Entry points
+    //
+
+    /**
+    * Invoke this if you have a StateManagerInternal for the object that
+    * you're fetching.  For example, see FetchRequest.handleReply().
+    */
+    void fetch(StateManagerInternal sm, OID oid) throws IOException {
+        this.sm = sm;
+        this.oldOID = oid;
+        fetch();
+    }
+
+    /**
+    * Invoke this if you have an OID for the object that you're fetching.
+    * For example, see GetExtentRequest.handleReply().
+    */
+    StateManagerInternal fetch(OID oid) throws IOException {
+        this.oid = oid;
+        fetch();
+        return sm;
+    }
+
+            
+    /**
+     * Fetches data from input, resulting in an PersistenceCapable object
+     * with state from the datastore.  The format of the data is as per that
+     * described in InsertRequest.
+     */
+    private void fetch() throws IOException {
+        String className = fin.readUTF();
+        FOStoreSchemaUID fsuid = FOStoreSchemaUID.read(fin);
+        if (logger.isDebugEnabled()) {
+            logger.debug("FF.fetch/1: className=" + className + // NOI18N
+                ", fsuid=" + fsuid + ", oid=" + oid); // NOI18N
+        }
+
+        // Class of the instance that we are loading.
+        Class instanceClass = null;
+
+        // JDOClass corresponding to instanceClass.
+        JDOClass jdoClass = null;
+
+        // ClassLoader of the instance we are loading.
+        ClassLoader loader = null;
+
+        try {
+            instanceClass = pm.loadClass(className, candidateLoader);
+            jdoClass = model.getJDOClass(instanceClass);
+            
+            FOStoreSchemaUID instanceClassFsuid =
+                FOStoreSchemaUID.lookup(instanceClass, model);
+            if ( ! instanceClassFsuid.equals(fsuid)) {
+                throw new JDOUserException(
+                    msg.msg("EXC_FsuidMismatch", className)); // NOI18N
+            }
+            loader = instanceClass.getClassLoader();
+
+            // If we have an oid, we might not yet have the classname/CLID
+            // mapping.  Make it so.
+            if (null != oid) {
+                CLID clid = oid.getCLID();
+                if (model.getClass(clid) == null) {
+                    if (logger.isDebugEnabled()) {
+                        logger.debug(
+                            "FF.fetch/1a: putting for " + // NOI18N
+                            instanceClass.getName()  + ", " + clid); // NOI18N
+                    }
+                    model.put(instanceClass, clid);
+                }
+            }
+        } catch (ClassNotFoundException ex) {
+            throw new JDOUserException(
+                msg.msg("EXC_CannotLoadInstanceClass", className)); // NOI18N
+        }
+
+        // We need read the CLID/classname pairs *before* reading the data
+        // which contains fields using those CLID's, so that we can establish
+        // a mapping that the FieldFetcher (and StateManager) will use to
+        // create instances of those classes.
+        synchronized(fin) {
+            int fieldsLength = fin.readInt();
+            int fieldsPos = fin.getPos(); // Save for later
+            fin.advance(fieldsLength);
+
+            //
+            // Read the CLID/classname pairs, and make sure that we have
+            // both loaded the class and mapped the class to the CLID
+            //
+            
+            int size = fin.readInt(); // number of CLID/classname pairs
+            for (int i = 0; i < size; i++) {
+                CLID clid = CLID.read(fin);
+                String fieldClassName = fin.readUTF();
+                FOStoreSchemaUID flduid = FOStoreSchemaUID.read(fin);
+
+                Class fieldClass = model.getClass(clid);
+
+                if (logger.isDebugEnabled()) {
+                    logger.debug("FF.fetch/2: fieldClassName=" + // NOI18N
+                                   fieldClassName + 
+                                   ", fieldClass=" + fieldClass + // NOI18N
+                                   ", " + clid + // NOI18N
+                                   ", flduid=" + flduid); // NOI18N
+                }
+
+                if (fieldClass != null) {
+                    // The class is already loaded, just do a sanity check.
+                    if (!fieldClassName.equals(fieldClass.getName())) {
+                        throw new FOStoreFatalInternalException(
+                            getClass(), "handleReply", // NOI18N
+                            msg.msg("ERR_ClassMismatch", // NOI18N
+                                    className,
+                                    fieldClassName,
+                                    fieldClass.getName()));
+                    }
+                } else {
+                    try {
+                        fieldClass = pm.loadClass(fieldClassName, loader);
+
+                        // If the FOStoreSchemaUID for fieldClass doesn't
+                        // match flduid, then we've got a structural mismatch
+                        // between the class in the database and the class in
+                        // the current JVM.
+                        if (!
+                            flduid.equals(FOStoreSchemaUID.lookup(fieldClass, model))) {
+                            throw new JDOUserException(
+                                msg.msg(
+                                    "EXC_FsuidMismatch", fieldClassName)); // NOI18N
+                        }
+                        
+                        if (logger.isDebugEnabled()) {
+                            logger.debug(
+                                "FF.fetch/3: putting for " + // NOI18N
+                                fieldClass.getName() +
+                                ", " + jdoClass + //  NOI18N
+                                ", " + clid); // NOI18N
+                        }
+                        model.put(fieldClass, clid);
+                    } catch (ClassNotFoundException ex) {
+                        throw new JDOUserException(
+                            msg.msg("EXC_CannotLoadFieldClass", // NOI18N
+                                    className, fieldClassName));
+                    }
+                }
+            }
+
+            // sm will be null if we were invoked via the "fetch(oid)" entry
+            // point.  In that case, pm.getStateManager(oid) is only safe
+            // once we have gone through the above CLID/classname mapping.
+            if (null == sm) {
+                sm = pm.getStateManager(oid, instanceClass);
+                sm.setPCClass(instanceClass); // this will be a no-op if sm is replaced above.
+            } else {
+                // It may be the case when StateManager did not know the
+                // actual type of the instance Class (application identity)
+                // Read the actual CLID from the stream.
+                CLID newCLID = CLID.read(fin);
+                if (oldOID != null && !oldOID.isDataStoreIdentity()) {
+                    if (logger.isDebugEnabled()) {
+                        logger.debug(
+                            "FF.fetch: check OID=" + oldOID + " for SM=" + sm); // NOI18N
+                    }
+                    long uid = oldOID.getUID();
+                    CLID clid = oldOID.getCLID();
+                    if (!newCLID.equals(clid)) {
+                        FOStorePMF pmf = (FOStorePMF)pm.getPersistenceManagerFactory();
+                        oldOID.replaceProvisionalOIDWithReal(OID.create(newCLID, uid), null, null);
+
+                        if (logger.isDebugEnabled()) {
+                            logger.debug(
+                                "FF.fetch: new OID=" + oldOID + ", SM=" + sm); // NOI18N
+                        }
+                    }
+                }
+                sm.setPCClass(instanceClass); // this will be a no-op if sm is replaced above.
+            }
+
+            // Save this end-of-data position for later use
+            int endPos = fin.getPos();
+            
+            // Set the stream's position for reading data values, and get
+            // them.
+            fin.setPos(fieldsPos);
+
+            // XXX We should be using the field numbers as given to FetchRequest.
+            int fields[] = jdoClass.getPersistentFieldNumbers();
+            int numFields = fields.length;
+            if (logger.isDebugEnabled()) {
+                logger.debug(
+                    "FF.fetch/4: numFields=" + numFields); // NOI18N
+            }
+            currNum = 0;
+            cls = sm.getPCClass();
+            sm.replace(fields, this);
+
+            fin.setPos(endPos);
+        }
+    }
+
+    void setPCClass(Class pcClass) {
+        cls = pcClass;
+    }
+
+    public boolean fetchBooleanField(int fieldNum) {
+        boolean rc = false;
+        
+        skipFields(fieldNum);
+        FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+        try {
+            rc = t.fetchBoolean(fin);
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                this.getClass(), "fetchBooleanField", ex); // NOI18N
+        }
+        return rc;
+    }
+    
+    public char fetchCharField(int fieldNum) {
+        char rc = ' ';
+        
+        skipFields(fieldNum);
+        FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+        try {
+            rc = t.fetchChar(fin);
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                this.getClass(), "fetchCharField", ex); // NOI18N
+        }
+        return rc;
+    }
+   
+    public byte fetchByteField(int fieldNum) {
+        byte rc = 0;
+        
+        skipFields(fieldNum);
+        FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+        try {
+            rc = t.fetchByte(fin);
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                this.getClass(), "fetchByteField", ex); // NOI18N
+        }
+        return rc;
+    }
+
+    public short fetchShortField(int fieldNum) {
+        short rc = 0;
+        
+        skipFields(fieldNum);
+        FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+        try {
+            rc = t.fetchShort(fin);
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                this.getClass(), "fetchShortField", ex); // NOI18N
+        }
+        return rc;
+    }
+
+    public int fetchIntField(int fieldNum) {
+        int rc = 0;
+        
+        skipFields(fieldNum);
+        FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+        try {
+            rc = t.fetchInt(fin);
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                this.getClass(), "fetchIntField", ex); // NOI18N
+        }
+        return rc;
+    }
+
+    public long fetchLongField(int fieldNum) {
+        long rc = 0L;
+        
+        skipFields(fieldNum);
+        FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+        try {
+            rc = t.fetchLong(fin);
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                this.getClass(), "fetchLongField", ex); // NOI18N
+        }
+        return rc;
+    }
+
+    public float fetchFloatField(int fieldNum) {
+        float rc = 0.0F;
+        
+        skipFields(fieldNum);
+        FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+        try {
+            rc = t.fetchFloat(fin);
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                this.getClass(), "fetchFloatField", ex); // NOI18N
+        }
+        return rc;
+    }
+
+    public double fetchDoubleField(int fieldNum) {
+        double rc = 0.0;
+        
+        skipFields(fieldNum);
+        FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+        try {
+            rc = t.fetchDouble(fin);
+        } catch (IOException ex) {
+            throw new FOStoreFatalIOException(
+                this.getClass(), "fetchDoubleField", ex); // NOI18N
+        }
+        return rc;
+    }
+
+    public String fetchStringField(int fieldNum) {
+        String rc = ""; // NOI18N
+        
+        skipFields(fieldNum);
+        FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+        try {
+            // Need to pass all correct parameters as this can be
+            // a nested request and we don't want to override important
+            // info with null's.
+            rc = (String)t.fetchObject(fin, sm, fieldNum, pm); 
+        } catch (Exception ex) {
+            throw new FOStoreFatalInternalException(
+                this.getClass(), "fetchStringField", ex); // NOI18N
+        }
+        return rc;
+    }
+
+    public Object fetchObjectField(int fieldNum) {
+        Object rc = null;
+        
+        skipFields(fieldNum);
+        FOStoreTranscriber t = model.getTranscriber(cls, fieldNum);
+        try {
+            rc = t.fetchObject(fin, sm, fieldNum, pm);
+        } catch (Exception ex) {
+            throw new FOStoreFatalInternalException(
+                this.getClass(), "fetchObjectField", ex); // NOI18N
+        }
+        return rc;
+    }
+
+    private void skipFields(int fieldNum) {
+        if (skip) {
+            while(currNum < fieldNum) {
+                FOStoreTranscriber t = model.getTranscriber(cls, currNum);
+                try {
+                    t.skip(fin);
+                } catch (Exception ex) {
+                    throw new FOStoreFatalInternalException(
+                        this.getClass(), "skipFields", ex); // NOI18N
+                }
+                currNum++;
+            }
+            currNum++; // for the next time.
+        } // do nothing otherwise.
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FieldRequest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FieldRequest.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FieldRequest.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FieldRequest.java Sun May 22 11:40:13 2005
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * Represents a request to manipulate (read or update) the fields of an
+ * object.
+ *
+ * @author Dave Bristor
+ */
+interface FieldRequest extends Request {
+    /**
+      * Indicates which fields are to be manipulated in the object.
+      * @param fieldNums The set of field numbers indicating the fields that
+      * are to be manipulated.
+      */
+    public void setFieldNums(int fieldNums[]);
+
+    /**
+      * Adds to the set of fields that are to be manipulated.
+      * @param fieldNum Number of the field to be manipulated.
+      */
+    public void addFieldNum(int fieldNum);
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FloatTranscriber.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FloatTranscriber.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FloatTranscriber.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FloatTranscriber.java Sun May 22 11:40:13 2005
@@ -0,0 +1,48 @@
+/*
+ * 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.DataOutput;
+import java.io.IOException;
+
+/**
+* Transcribes float values.
+*
+* @author Dave Bristor
+*/
+class FloatTranscriber extends FOStoreTranscriber {
+    private static FloatTranscriber instance = new FloatTranscriber();
+
+    private FloatTranscriber() {}
+
+    static FloatTranscriber getInstance() {
+        return instance;
+    }
+    
+    void storeFloat(float value, DataOutput out) throws IOException {
+        out.writeFloat(value);
+    }
+
+    float fetchFloat(DataInput in) throws IOException {
+        return in.readFloat();
+    }
+
+    void skip(DataInput in) throws IOException { 
+        in.readFloat(); 
+    }
+}

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetClassHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetClassHandler.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetClassHandler.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetClassHandler.java Sun May 22 11:40:13 2005
@@ -0,0 +1,95 @@
+/*
+ * 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.DataOutput;
+import java.io.IOException;
+
+import javax.jdo.JDOUserException;
+
+import org.apache.jdo.util.I18NHelper;
+
+/**
+* Process GetClass requests.
+*
+* @author Dave Bristor
+*/
+// This is server-side code.  It does not need to live in the client.
+class GetClassHandler extends RequestHandler {
+
+    /** I18N support. */
+    private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+    private GetClassHandler(Reply reply, int length,
+                         FOStoreServerConnection con) {
+
+        super(reply, length, con);
+    }
+    
+    public static final HandlerFactory factory =
+        new HandlerFactory() {
+                public RequestHandler getHandler(Reply reply, int length,
+                                             FOStoreServerConnection con) {
+                return new GetClassHandler(reply, length, con);
+            }};
+
+    RequestFinisher handleRequest()
+        throws IOException, FOStoreDatabaseException {
+
+        DataInput in = con.getInputFromClient();
+        FOStoreDatabase db = con.getDatabase();
+        CLID clid = CLID.read(in);
+
+        OID oid = db.getDBInfo().getDBClassOID(clid);
+        if (logger.isDebugEnabled()) {
+            logger.debug(
+                "GetClassHandler.hR/0: " + clid +  // NOI18N
+                " " + Tester.toHex(clid.getId(), 8) + ", " + oid + // NOI18N
+                " " + Tester.toHex(oid.oid, 16)); // NOI18N
+        }
+        
+        FOStoreDatabase fodb = con.getDatabase();
+        try {
+            DBClass dbClass = (DBClass)fodb.getIfExists(oid);
+            if (null == dbClass) {
+                reply.setStatus(
+                    Status.ERROR, 
+                    msg.msg("EXC_DoesNotExist", oid.toString())); // NOI18N
+            } else {
+                String className = dbClass.getName();
+                reply.writeUTF(className);
+                reply.setStatus(Status.OK);
+                if (logger.isDebugEnabled()) {
+                    logger.debug(
+                        "GetClassHandler.hR/1: " + className); // NOI18N
+                }
+            }
+
+        } catch (ClassCastException ex) {
+            reply.setStatus(Status.ERROR, ex);
+        }
+        
+        return null;
+    }
+}
+
+
+
+
+
+

Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetClassRequest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetClassRequest.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetClassRequest.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/GetClassRequest.java Sun May 22 11:40:13 2005
@@ -0,0 +1,93 @@
+/*
+ * 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 javax.jdo.JDOUserException;
+
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+ * Represents a request to get the java.lang.Class corresponding to a CLID.
+ *
+ * @author Dave Bristor
+ */
+//
+// This is client-side code.  It does not need to live in the server.
+//
+class GetClassRequest extends AbstractRequest {
+    /** The CLID of the class sought by this request. */
+    private final CLID clid;
+    
+    /** PersistenceManagerInternal used to load the class. */
+    private final PersistenceManagerInternal pm;
+
+    /** The Class sought by this request. */
+    private Class classForCLID;
+
+    GetClassRequest(CLID clid, Message m,
+                    FOStorePMF pmf, PersistenceManagerInternal pm) {
+        super(m, pmf);
+        this.clid = clid;
+        this.classForCLID = null;
+        this.pm = pm;
+    }
+
+    protected void doRequestBody() throws IOException {
+        clid.write(out);
+        if (logger.isDebugEnabled()) {
+            logger.debug("GetClassRequest.dRB: " + clid); // NOI18N
+        }
+    }
+
+     public void handleReply(Status status, DataInput in, int length)
+        throws IOException {
+
+        String className = in.readUTF();
+        if (logger.isDebugEnabled()) {
+            logger.debug("GetClassRequest.hR: className=" + className // NOI18N
+                           + " status=" + status); // NOI18N
+        }
+        // className is valid if not empty and request succeeded.
+        if (null != className
+            && className.length() > 0
+            && Status.OK.equals(status)) {
+            
+            try {
+                classForCLID = pm.loadClass(className, null);
+                // Bind in the metadata
+                FOStoreModel model = pmf.getModel();
+                model.put(classForCLID, clid);
+
+                if (logger.isDebugEnabled()) {
+                    logger.debug("GetClassRequest.hR: classForCLID=" + classForCLID); // NOI18N
+                }
+            } catch (ClassNotFoundException ex) {
+               throw new JDOUserException(
+                   msg.msg("EXC_NoClassForCLID", clid, ex)); // NOI18N
+            }
+        }
+    }
+
+    Class getClassForCLID() {
+        return classForCLID;
+    }
+}