db-jdo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From m..@apache.org
Subject svn commit: r158176 [21/79] - in incubator/jdo/trunk/ri11: ./ src/ src/conf/ src/java/ src/java/org/ src/java/org/apache/ src/java/org/apache/jdo/ src/java/org/apache/jdo/ejb/ src/java/org/apache/jdo/enhancer/ src/java/org/apache/jdo/impl/ src/java/org/apache/jdo/impl/enhancer/ src/java/org/apache/jdo/impl/enhancer/classfile/ src/java/org/apache/jdo/impl/enhancer/core/ src/java/org/apache/jdo/impl/enhancer/generator/ src/java/org/apache/jdo/impl/enhancer/meta/ src/java/org/apache/jdo/impl/enhancer/meta/model/ src/java/org/apache/jdo/impl/enhancer/meta/prop/ src/java/org/apache/jdo/impl/enhancer/meta/util/ src/java/org/apache/jdo/impl/enhancer/util/ src/java/org/apache/jdo/impl/fostore/ src/java/org/apache/jdo/impl/jdoql/ src/java/org/apache/jdo/impl/jdoql/jdoqlc/ src/java/org/apache/jdo/impl/jdoql/scope/ src/java/org/apache/jdo/impl/jdoql/tree/ src/java/org/apache/jdo/impl/model/ src/java/org/apache/jdo/impl/model/java/ src/java/org/apache/jdo/impl/model/java/runtime/ src/java/org/apache/jdo/impl/model/jdo/ src/java/org/apache/jdo/impl/model/jdo/caching/ src/java/org/apache/jdo/impl/model/jdo/util/ src/java/org/apache/jdo/impl/model/jdo/xml/ src/java/org/apache/jdo/impl/pm/ src/java/org/apache/jdo/impl/sco/ src/java/org/apache/jdo/impl/state/ src/java/org/apache/jdo/jdoql/ src/java/org/apache/jdo/jdoql/tree/ src/java/org/apache/jdo/model/ src/java/org/apache/jdo/model/java/ src/java/org/apache/jdo/model/jdo/ src/java/org/apache/jdo/pm/ src/java/org/apache/jdo/sco/ src/java/org/apache/jdo/state/ src/java/org/apache/jdo/store/ src/java/org/apache/jdo/util/ test/ test/conf/ test/enhancer/ test/enhancer/sempdept/ test/enhancer/sempdept/src/ test/enhancer/sempdept/src/empdept/ 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/ xdocs/
Date Sat, 19 Mar 2005 01:06:02 GMT
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreLocalConnection.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreLocalConnection.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreLocalConnection.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreLocalConnection.java Fri Mar 18 17:02:29 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/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreLoginException.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreLoginException.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreLoginException.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreLoginException.java Fri Mar 18 17:02:29 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/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreModel.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreModel.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreModel.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreModel.java Fri Mar 18 17:02:29 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/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreOutput.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreOutput.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreOutput.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreOutput.java Fri Mar 18 17:02:29 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/ri11/src/java/org/apache/jdo/impl/fostore/FOStorePMF.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStorePMF.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStorePMF.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStorePMF.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,800 @@
+/*
+ * 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.PrintWriter;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.naming.Referenceable;
+import javax.naming.StringRefAddr;
+
+import javax.jdo.JDOException;
+import javax.jdo.JDOFatalException;
+import javax.jdo.PersistenceManager;
+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.impl.pm.PersistenceManagerFactoryImpl;
+import org.apache.jdo.impl.pm.PersistenceManagerImpl;
+import org.apache.jdo.model.jdo.JDOClass;
+import org.apache.jdo.pm.PersistenceManagerFactoryInternal;
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.store.StoreManager;
+import org.apache.jdo.store.TranscriberFactory;
+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.
+//
+
+/**
+* The File/Object Store's implementation of a PersistenceManagerFactory.
+* <p>
+* This class is <code>public</code> so that clients can create instances of it
+* with <code>new</code>.
+*
+* @author Dave Bristor
+*/
+public class FOStorePMF
+    extends PersistenceManagerFactoryImpl
+    implements Externalizable, Referenceable
+{
+    /**
+     * StoreManagers provided by this PMF, one per-PM.
+     */
+    private transient final HashMap storeManagers = new HashMap();
+
+    /**
+     * Map provisional id's that were created on behalf of this PMF to the
+     * real id's that have been returned by various StoreManager instances
+     * that are bound to this PMF.
+     */
+    private transient final WeakHashMap provisionalOIDs = new WeakHashMap();
+
+    // ConnectionFactory associated with this PMF.
+    private transient FOStoreConnectionFactory cf;
+
+    /** Model associated with this PMF. */
+    private transient final FOStoreModel model = new FOStoreModel();
+    
+    /** Flag to tell whether to create.  This is not a JDO property.
+     */
+    private boolean create;
+
+    /** The Properties instance from which this PersistenceManagerFactory
+     * was configured. This is the key into the Properties/PersistenceManagerFactory
+     * map.
+     */
+    private Properties configuredFrom = null;
+    
+    /** 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, FOStorePMF.class.getClassLoader());
+
+    /** Logger */
+    static final Log logger = LogFactory.getFactory().getInstance(
+        "org.apache.jdo.impl.fostore"); // NOI18N
+    
+    /** JNDI property type
+     */
+    static final String addrType =
+        "Serialized-org.apache.jdo.impl.fostore.FOStorePMF"; // NOI18N
+    
+    /** Supported list of options for this implementation.
+     */
+    private final String[] optionArray = new String[] {
+        "javax.jdo.option.TransientTransactional", // NOI18N
+        "javax.jdo.option.NontransactionalRead", // NOI18N
+        "javax.jdo.option.NontransactionalWrite", // NOI18N
+        "javax.jdo.option.RetainValues", // NOI18N
+        "javax.jdo.option.Optimistic", // NOI18N
+        "javax.jdo.option.ApplicationIdentity", // NOI18N
+        "javax.jdo.option.DatastoreIdentity", // NOI18N
+//        "javax.jdo.option.NonDatastoreIdentity", // NOI18N
+        "javax.jdo.option.ArrayList", // NOI18N
+        "javax.jdo.option.HashMap", // NOI18N
+        "javax.jdo.option.Hashtable", // NOI18N
+        "javax.jdo.option.LinkedList", // NOI18N
+        "javax.jdo.option.TreeMap", // NOI18N
+        "javax.jdo.option.TreeSet", // NOI18N
+        "javax.jdo.option.Vector", // NOI18N
+//            "javax.jdo.option.Map", // NOI18N
+//            "javax.jdo.option.List", // NOI18N
+        "javax.jdo.option.Array", // NOI18N
+        "javax.jdo.option.NullCollection", // NOI18N
+        "javax.jdo.query.JDOQL" // NOI18N
+    };
+    
+    /** Properties accessors hash map for fostore-specific properties.
+     */
+    protected static HashMap fostorePropsAccessors = new HashMap(3);
+
+    /**
+     * Mapping of supported java.util classes to the tracked
+     * SCO classes in org.apache.jdo.impl.sco package
+     */  
+    private static HashMap trackedClasses = new HashMap();
+    
+    /** Initialize fostorePropsAccessors.
+     */
+    // XXX Jikes bug
+    // If this is protected, FOStorePMF.initPropsAccessors cannot invoke it,
+    // due to a bug in jikes (http://www-124.ibm.com/developerworks/bugs/?func=detailbug&bug_id=213&group_id=10)
+    //protected static void initPropsAccessors() {
+    //
+    public static void initPropsAccessors() {
+        PersistenceManagerFactoryImpl.initPropsAccessors();
+          if (fostorePropsAccessors.size() != 0) 
+              return;
+          synchronized (fostorePropsAccessors) {
+              if (fostorePropsAccessors.size() != 0) {
+                  return;
+              }
+              fostorePropsAccessors.put(
+              "org.apache.jdo.ConnectionCreate", // NOI18N
+              new PMFAccessor() {
+              public String get(PersistenceManagerFactoryImpl pmf) { return new Boolean(((FOStorePMF)pmf).getConnectionCreate()).toString(); }
+              public String getNonDefault(PersistenceManagerFactoryImpl pmf) { return (!((FOStorePMF)pmf).getConnectionCreate())?null:"true"; } // NOI18N
+              public String getDefault() { return "false"; } // NOI18N
+              public void set(PersistenceManagerFactoryImpl pmf, String s) { ((FOStorePMF)pmf).setConnectionCreate(Boolean.valueOf(s).booleanValue()); }
+              });
+            fostorePropsAccessors.put(
+                "org.apache.jdo.option.QueryTimeout", // NOI18N
+                new PMFAccessor() {
+                public String get(PersistenceManagerFactoryImpl pmf) { return Integer.toString(pmf.getQueryTimeout()); }
+                public String getNonDefault(PersistenceManagerFactoryImpl pmf) { return (pmf.getQueryTimeout()==0)?null:Integer.toString(pmf.getQueryTimeout()); }
+                public String getDefault() { return "0"; } // NOI18N
+                public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setQueryTimeout(toInt(s)); }
+            });
+            fostorePropsAccessors.put(
+                "org.apache.jdo.option.UpdateTimeout", // NOI18N
+                new PMFAccessor() {
+                public String get(PersistenceManagerFactoryImpl pmf) { return Integer.toString(pmf.getUpdateTimeout()); }
+                public String getNonDefault(PersistenceManagerFactoryImpl pmf) { return (pmf.getUpdateTimeout()==0)?null:Integer.toString(pmf.getUpdateTimeout()); }
+                public String getDefault() { return "0"; } // NOI18N
+                public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setUpdateTimeout(toInt(s)); }
+            });
+          }
+      }
+
+      /** Return the FOStore-specific accessors (the
+       * properties that are not in the JDO specification).
+       * @return the hash map of FOStore accessors
+       */      
+    protected HashMap getLocalAccessors() {
+        initPropsAccessors();
+        return fostorePropsAccessors;
+    }
+
+    /** Initialize trackedClasses.
+     */  
+    private void initTrackedClasses() {
+        if (trackedClasses.size() != 0) {
+            return;
+        }
+        synchronized (trackedClasses) {
+            if (trackedClasses.size() != 0) {
+               return;
+            }  
+
+            // We will need to compare equals to ensure that we do not override
+            // user's defined classes:
+
+            // java.util.Date and java.sql classes:
+            trackedClasses.put(java.util.Date.class,
+                org.apache.jdo.impl.sco.Date.class);
+            trackedClasses.put(org.apache.jdo.impl.sco.Date.class,
+                org.apache.jdo.impl.sco.Date.class);
+            trackedClasses.put(java.sql.Date.class,
+                org.apache.jdo.impl.sco.SqlDate.class);
+            trackedClasses.put(org.apache.jdo.impl.sco.SqlDate.class,
+                org.apache.jdo.impl.sco.SqlDate.class);
+            trackedClasses.put(java.sql.Time.class,
+                org.apache.jdo.impl.sco.SqlTime.class);
+            trackedClasses.put(org.apache.jdo.impl.sco.SqlTime.class,
+                org.apache.jdo.impl.sco.SqlTime.class);
+            trackedClasses.put(java.sql.Timestamp.class,
+                org.apache.jdo.impl.sco.SqlTimestamp.class);
+            trackedClasses.put(org.apache.jdo.impl.sco.SqlTimestamp.class,
+                org.apache.jdo.impl.sco.SqlTimestamp.class);
+
+            // java.util.Set
+            trackedClasses.put(java.util.HashSet.class,
+                org.apache.jdo.impl.sco.HashSet.class);
+            trackedClasses.put(java.util.AbstractSet.class,
+                org.apache.jdo.impl.sco.HashSet.class);
+            trackedClasses.put(java.util.Set.class,
+                org.apache.jdo.impl.sco.HashSet.class);
+            trackedClasses.put(org.apache.jdo.impl.sco.HashSet.class,
+                org.apache.jdo.impl.sco.HashSet.class);
+
+            // java.util.List
+            trackedClasses.put(java.util.ArrayList.class,
+                org.apache.jdo.impl.sco.ArrayList.class);
+            trackedClasses.put(java.util.AbstractList.class,
+                org.apache.jdo.impl.sco.ArrayList.class);
+            trackedClasses.put(java.util.List.class,
+                org.apache.jdo.impl.sco.ArrayList.class);
+            trackedClasses.put(java.util.AbstractCollection.class,
+                org.apache.jdo.impl.sco.ArrayList.class);
+            trackedClasses.put(java.util.Collection.class,
+                org.apache.jdo.impl.sco.ArrayList.class);
+            trackedClasses.put(org.apache.jdo.impl.sco.ArrayList.class,
+                org.apache.jdo.impl.sco.ArrayList.class);
+
+            // java.util.Vector
+            trackedClasses.put(java.util.Vector.class,
+                org.apache.jdo.impl.sco.Vector.class);
+            trackedClasses.put(org.apache.jdo.impl.sco.Vector.class,
+                org.apache.jdo.impl.sco.Vector.class);
+
+            // java.util.SortedSet
+            trackedClasses.put(java.util.TreeSet.class,
+                org.apache.jdo.impl.sco.TreeSet.class);
+            trackedClasses.put(java.util.SortedSet.class,
+                org.apache.jdo.impl.sco.TreeSet.class);
+            trackedClasses.put(org.apache.jdo.impl.sco.TreeSet.class,
+                org.apache.jdo.impl.sco.TreeSet.class);
+
+            // java.util.LinkedList
+            trackedClasses.put(java.util.LinkedList.class,
+                org.apache.jdo.impl.sco.LinkedList.class);
+            trackedClasses.put(java.util.AbstractSequentialList.class,
+                org.apache.jdo.impl.sco.LinkedList.class);
+            trackedClasses.put(org.apache.jdo.impl.sco.LinkedList.class,
+                org.apache.jdo.impl.sco.LinkedList.class);
+    
+            // java.util.Map
+            trackedClasses.put(java.util.Map.class,
+                org.apache.jdo.impl.sco.HashMap.class);
+            trackedClasses.put(java.util.AbstractMap.class,
+                org.apache.jdo.impl.sco.HashMap.class);
+            trackedClasses.put(java.util.HashMap.class,
+                org.apache.jdo.impl.sco.HashMap.class);
+            trackedClasses.put(org.apache.jdo.impl.sco.HashMap.class,
+                org.apache.jdo.impl.sco.HashMap.class);
+
+            // java.util.Hashtable
+            trackedClasses.put(java.util.Hashtable.class,
+                org.apache.jdo.impl.sco.Hashtable.class);
+            trackedClasses.put(org.apache.jdo.impl.sco.Hashtable.class,
+                org.apache.jdo.impl.sco.Hashtable.class);
+
+            // java.util.SortedMap
+            trackedClasses.put(java.util.SortedMap.class,
+                org.apache.jdo.impl.sco.TreeMap.class);
+            trackedClasses.put(java.util.TreeMap.class,
+                org.apache.jdo.impl.sco.TreeMap.class);
+            trackedClasses.put(org.apache.jdo.impl.sco.TreeMap.class,
+                org.apache.jdo.impl.sco.TreeMap.class);
+        }
+    }
+    
+    //
+    // Methods from PersistenceManagerFactory that are not already
+    // implemented in org.apache.jdo.impl.pm.PersistenceManagerFactoryImpl.
+    //
+    
+    /** Create a new instance of PersistenceManager with
+     * the specific user name and password.
+     * @see org.apache.jdo.impl.pm.PersistenceManagerFactoryImpl#createPersistenceManager(String userid, String password)
+     * @param userid the user name
+     * @param password the password
+     * @return the Persistencemanager
+     */
+    protected PersistenceManager createPersistenceManager(
+        String userid, String password) {
+
+        PersistenceManager rc = null;
+        try {
+            rc = new PersistenceManagerImpl(this, userid, password);
+            setConfigured();
+        } catch (JDOException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            throw new FOStoreFatalInternalException(
+                getClass(), "createPersistenceManager(userid, password)", ex); // NOI18N
+        }
+        return rc;
+    }
+
+    /** Close this PersistenceManagerFactory. Check for 
+    * JDOPermission("closePersistenceManagerFactory") and if not authorized, 
+    * throw SecurityException. 
+    * <P>If the authorization check succeeds, check to see that all 
+    * PersistenceManager instances obtained from this PersistenceManagerFactory 
+    * have no active transactions. If any PersistenceManager instances have 
+    * an active transaction, throw a JDOUserException, with one nested 
+    * JDOUserException for each PersistenceManager with an active Transaction. 
+    * <P>If there are no active transactions, then close all PersistenceManager 
+    * instances obtained from this PersistenceManagerFactory, mark this 
+    * PersistenceManagerFactory as closed, disallow getPersistenceManager 
+    * methods, and allow all other get methods. If a set method or 
+    * getPersistenceManager method is called after close, then 
+    * JDOUserException is thrown.
+    */
+    public void close() {
+        super.close();
+        /* remove this PMF from the map so another PMF with the same 
+         * properties can be constructed.
+         */
+        if (configuredFrom != null) {
+            synchronized (hashMapByFilteredProperties) {
+                hashMapByFilteredProperties.remove(configuredFrom);
+            }
+        }
+        close(true);
+    }
+
+    /**
+    * Closes the database unless there are any active store managers.
+    * @param force If true, forces the database to close anyway, regardless of
+    * whether or not any store managers are still active.
+    * @return true if the database was closed, false if not (i.e., force is
+    * false and there are active store managers).
+    * @see javax.jdo.PersistenceManagerFactory#getPersistenceManager
+    */
+    public boolean close(boolean force) {
+        boolean rc = false;
+
+        try {
+            if (storeManagers.isEmpty() || force) {
+                if (logger.isDebugEnabled()) {
+                    logger.debug("FOPMF closing database"); // NOI18N
+                }
+                if (null != cf) {
+                    cf.closeDatabase();
+                    cf = null;
+                }
+                rc = true;
+            }
+        } catch (JDOException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            throw new FOStoreFatalInternalException(
+                getClass(), "close", ex); // NOI18N
+        }
+        return rc;
+    }
+
+    //
+    // Methods from PersistenceManagerFactoryInternal
+    //
+    
+    /** Override PersistenceManagerFactoryImpl's method so we can use our
+     * own cf variable.
+     * @param cf the connection factory
+     */
+    public void setConnectionFactory(Object cf) {
+        this.cf = (FOStoreConnectionFactory) cf;
+    }
+    
+    /**
+     * Override PersistenceManagerFactoryImpl's method so that we can get a
+     * handle on the connection factory to close the database at close() time.
+     * @see org.apache.jdo.impl.pm.PersistenceManagerFactoryImpl#getConnectionFactory
+     * @return  the connection factory
+     */
+    public synchronized Object getConnectionFactory () {
+        FOStoreConnectionFactory rc = cf;
+
+        // If we already have a connection factory, use that.  Otherwise, if
+        // our superclass has one, use that.  Otherwise, make one, and use
+        // that.  In the latter 2 cases, set our connection factory to be the
+        // one acquired/made.
+        if (null == rc) {
+            try {
+                cf = (FOStoreConnectionFactory)super.getConnectionFactory();
+                if (logger.isDebugEnabled()) {
+                    logger.debug("FOPMF.getCF: super.cf = " + cf); // NOI18N
+                }
+                if (null == cf) {
+                    String cfName = getConnectionFactoryName();
+                    if (null != cfName) {
+                        // cf = JNDI lookup of name
+                        // XXX In what context?
+                    }
+                }
+                if (null == cf) {
+                    cf = new FOStoreConnectionFactory();
+                    cf.setPMF(this);
+                    cf.setUserName(getConnectionUserName());
+                    cf.setPassword(password);
+                    cf.setURL(getConnectionURL());
+                    cf.setCreate(create);
+                }
+                rc = cf;
+            } catch (JDOException ex) {
+                throw ex;
+            } catch (Exception ex) {
+                throw new FOStoreFatalInternalException(
+                    getClass(), "getConnectionFactory", ex); // NOI18N
+            }
+        }
+        return rc;        
+    }
+    
+    /** Verifies that the associated connection factory
+     * is configured (at least the URL is specified).
+     * @return if the connection factory is properly configured
+     */    
+    protected boolean isConnectionFactoryConfigured() {
+        return (cf==null?false:cf.isConfigured());
+    }
+
+    /**
+     * @see org.apache.jdo.pm.PersistenceManagerFactoryInternal#getTranscriberFactory()
+     * @return The PersistenceManagerFactory's transcriber factory.
+     */
+    public TranscriberFactory getTranscriberFactory() {
+        return FOStoreTranscriberFactory.getInstance();
+    }
+
+    /**
+    * If parameter is non-null and implements PersistenceCapable, returns
+    * OID.class.
+    * @see org.apache.jdo.pm.PersistenceManagerFactoryInternal#getObjectIdClass(
+    * Class cls)
+    */
+    public Class getObjectIdClass(Class cls) {
+        Class rc = null;
+        if (null != cls && PersistenceCapable.class.isAssignableFrom(cls)) {
+            JDOClass jdoClass = model.getJDOClass(cls);
+            rc = javaModelFactory.getJavaClass(jdoClass.getObjectIdClass());
+            if (rc == null)
+                rc = OID.class;
+        }
+        return rc;
+    }
+
+    /**
+    * @see org.apache.jdo.pm.PersistenceManagerFactoryInternal#getStoreManager(
+    * PersistenceManager pm)
+    */
+    public StoreManager getStoreManager(PersistenceManager pm) {
+        FOStoreStoreManager rc = null;
+        try {
+            rc = (FOStoreStoreManager)storeManagers.get(pm);
+            if (null == rc) {
+                rc = new FOStoreStoreManager(this);
+                storeManagers.put(pm, rc);
+            }
+        } catch (JDOException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            throw new FOStoreFatalInternalException(
+                getClass(), "getStoreManager", ex); // NOI18N
+        }
+        return rc;
+    }
+
+    /**
+    * @see org.apache.jdo.pm.PersistenceManagerFactoryInternal#releaseStoreManager(
+    * PersistenceManager pm)
+    */
+    public void releaseStoreManager(PersistenceManager pm) {
+        try {
+            storeManagers.remove(pm);
+        } catch (JDOException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            throw new FOStoreFatalInternalException(
+                getClass(), "releaseStoreManager", ex); // NOI18N
+        }
+    }
+
+    /**
+    * @see org.apache.jdo.pm.PersistenceManagerFactoryInternal#getTrackedClass(
+    * Class type)
+    */
+    public Class getTrackedClass(Class type) {
+        initTrackedClasses();
+        return (Class)trackedClasses.get(type);
+    }
+
+    /**
+    * Returns metadata associated with this PersistenceManagerFactory.
+    */
+    public FOStoreModel getModel() {
+        return model;
+    }
+
+    //
+    // Package-private methods
+    //
+    
+    /**
+    * Provides the request factory.
+    * <em>Currently, this is statically bound to return an instance of a
+    * {@link BufferedRequestFactory}.  In the future, this could be
+    * configurable.</em>
+    * @return A RequestFactory.
+    */
+    RequestFactory getRequestFactory() {
+        return BufferedRequestFactory.getInstance();
+    }
+
+    /**
+    * Sets up a mapping from the given provisional OID to real OID.
+    * @exception JDOFatalException Thrown if the given OID is not provisional, or if
+    * the given provisional OID is already mapped to a real OID.
+    */
+    // If you change this code, see method of same name in FOStoreDatabase.
+    void mapProvisionalOIDToReal(OID pOID, OID rOID) {
+        if (null == pOID || null == rOID || (! pOID.isProvisional())) {
+            throw new JDOFatalException(msg.msg("ERR_OIDNotProv", pOID)); // NOI18N
+        }
+        if (null != provisionalOIDs.get(pOID)) {
+            throw new JDOFatalException(msg.msg("ERR_DuplicateProvOID", pOID)); // NOI18N
+        }
+        provisionalOIDs.put(pOID, rOID);
+    }
+
+    /**
+    * Provides the real OID for the given provisional OID.  Returns null if
+    * there is no mapping.
+    * @exception JDOFatalException Thrown if the given OID is not provisional.
+    */
+    // If you change this code, see method of same name in FOStoreDatabase.
+    OID getRealOIDFromProvisional(OID pOID) {
+        if (null == pOID || (! pOID.isProvisional())) {
+            throw new JDOFatalException(msg.msg("ERR_OIDNotProv", pOID)); // NOI18N
+        }
+        return (OID)provisionalOIDs.get(pOID);
+    }
+
+    //
+    // Implement Externalizable
+    // Support for serialization.  We don't have any state to save, but want
+    // all the superclass's state saved
+    //
+
+    /**
+    * Writes this PMF's state to the given object output.
+    * @param out ObjectOutput to which this PMF's state is written.
+    */
+    public void writeExternal(java.io.ObjectOutput out)
+        throws java.io.IOException {
+
+        java.io.ObjectOutputStream oos = (java.io.ObjectOutputStream)out;
+        super.doWriteObject(oos);
+        oos.writeBoolean(create);
+    }
+
+    /**
+    * Reads this PMF's state from the given object input.
+    * @param in ObjectInput from which this PMF's state is read.
+    */
+    public void readExternal(java.io.ObjectInput in)
+        throws java.io.IOException, ClassNotFoundException {
+
+        java.io.ObjectInputStream ois = (java.io.ObjectInputStream)in;
+        super.doReadObject(ois);
+        create = ois.readBoolean();
+    }
+
+    /**
+      * Uses rot13 algorithm.
+      * @see org.apache.jdo.impl.pm.PersistenceManagerFactoryImpl#encrypt
+      */
+    protected String encrypt(String s) {
+        return doEncrypt(s);
+    }
+
+    /**
+      * Uses rot13 algorithm.
+      * @see org.apache.jdo.impl.pm.PersistenceManagerFactoryImpl#decrypt
+      */
+    protected  String decrypt(String s) {
+        return doEncrypt(s);
+    }
+    
+    /**
+     * Use same encryption for others in this package (e.g. FOStoreConnectionFactory).
+     */
+    static String doEncrypt(String s) {
+        return doDecrypt(s);
+    }
+
+    /**
+     * Use same encryption for others in this package (e.g. FOStoreConnectionFactory).
+     */
+    static String doDecrypt(String s) {
+        String rc = null;
+        if (null != s) {
+            rc = rot13(s);
+        }                
+        return rc;
+    }
+
+    // Standard Rot13 stuff.  Translated to Java from a C implementation found
+    // on the net.
+    private static String rot13(String s) {
+        String rc = null;
+        int length = s.length();
+        StringBuffer sb = new StringBuffer(length);
+        for (int i = 0; i < length; i++) {
+            int c = s.charAt(i);
+            int cap = c & 32;
+            c &= ~cap;
+            c = ((c >= 'A') && (c <= 'Z') ? ((c - 'A' + 13) % 26 + 'A') : c) | cap;
+            sb.append((char)c);
+        }
+        rc =  sb.toString();
+        if (logger.isDebugEnabled()) {
+            logger.debug("encrypted " + s + " to be " + rc); // NOI18N
+        }
+        return rc;
+    }
+        
+    /**
+     * @param create specifies whether to create the database */    
+    public void setConnectionCreate (boolean create) {
+        this.create = create;
+    }
+    
+    /**
+     * @param create tells whether to create the database*/    
+    public void setConnectionCreate (String create) {
+        this.create = Boolean.valueOf(create).booleanValue();
+    }
+    
+    /**
+     * @return whether to create the database */    
+    public boolean getConnectionCreate() {
+        return create;
+    }
+    
+    /**
+     * @see org.apache.jdo.impl.pm.PersistenceManagerFactoryImpl#setCFProperties
+     */
+    protected void setCFProperties(Properties p) {
+        if (null != cf) {
+            cf.setProperties(p);
+        }
+    }
+
+    /**
+     * @see org.apache.jdo.impl.pm.PersistenceManagerFactoryImpl#getCFFromProperties
+     */
+    protected void getCFFromProperties(Properties p) {
+        cf = new FOStoreConnectionFactory();
+        cf.setFromProperties(p);
+    }
+
+    //
+    // Implement Referenceable
+    //
+
+    /**
+     * Uses StringRefAddr's to store the information
+     */
+    public Reference getReference() throws NamingException {
+        Reference rc = new Reference(
+          FOStorePMF.class.getName(),
+          FOStorePMFFactory.class.getName(),
+          null);
+
+        Properties p = getAsProperties();
+        for (Enumeration e = p.propertyNames(); e.hasMoreElements();) {
+            String key = (String)e.nextElement();
+            String value = p.getProperty(key);
+            rc.add(new StringRefAddr(key, value));
+        }                
+        return rc;
+    }
+    
+    /**
+     * @return configuration information */    
+    public String toString() {
+        return super.toString() +
+            "model: " + model + "\n" + // NOI18N
+            "storeManagers: " + storeManagers + "\n" + // NOI18N
+            "provisionalOIDs: " + provisionalOIDs + "\n" + // NOI18N
+            "cf: " + cf + "\n"; // NOI18N
+    }
+
+    /**
+    * @see PersistenceManagerFactoryImpl#getOptionArray
+    */
+    protected String[] getOptionArray() {
+        return optionArray;
+    }
+    
+    /** A HashMap that associates PersistenceManagerFactory instances with a
+     * Properties instance.
+     */
+    protected static HashMap hashMapByFilteredProperties = new HashMap();
+    
+    /** 
+     * Construct a Properties instance from the given Properties.  Only
+     * those property entries recognized by this implementation will be 
+     * stored in the internal Properties instance.
+     *
+     * <P>This method attempts to find an existing PersistenceManagerFactory 
+     * with the properties as specified in the parameter.  Only the non-default
+     * properties are considered when trying to find a match.
+     *
+     * <P>This method cannot be implemented by the superclass because 
+     */
+    public static PersistenceManagerFactoryImpl getPersistenceManagerFactory (Properties props) {
+        initPropsAccessors();
+        FOStoreConnectionFactory.initPropsAccessors();
+        Properties filtered = new Properties();
+        filterProperties (props, filtered, pmfAccessors);
+        filterProperties (props, filtered, propsAccessors);
+        filterProperties (props, filtered, fostorePropsAccessors);
+        filterProperties (props, filtered, FOStoreConnectionFactory.CFpropsAccessors);
+        FOStorePMF pmf = null;
+        synchronized (hashMapByFilteredProperties) {
+            pmf = (FOStorePMF) hashMapByFilteredProperties.get (filtered);
+            if (pmf != null) return pmf;
+            pmf = new FOStorePMF();
+            pmf.setFromProperties (filtered);
+            pmf.verifyConfiguration();
+            pmf.setConfigured();
+            hashMapByFilteredProperties.put (filtered, pmf);
+            pmf.configuredFrom = filtered;
+        }
+        return pmf;
+    }
+            
+    /** Set the PMF class property for this PMF.
+     */
+    protected void setPMFClassProperty(Properties props) {
+        props.setProperty ("javax.jdo.PersistenceManagerFactoryClass", "org.apache.jdo.impl.fostore.FOStorePMF"); // NOI18N
+    }    
+
+    /** Method called by the shudown hook to close pmf instances left open 
+     * when the JVM exits.
+     */
+    protected void shutdown() {
+        super.shutdown();
+        close(true);
+    }
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStorePMFFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStorePMFFactory.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStorePMFFactory.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStorePMFFactory.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,65 @@
+/*
+ * 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.IOException;
+import java.io.ObjectInputStream;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Properties;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.Reference;
+import javax.naming.spi.ObjectFactory;
+import javax.naming.StringRefAddr;
+
+/**
+* Creates a FOStorePMF when read in via JNDI.
+* <p>
+* This class is <code>public</code> so that JNDI can create instances.
+*
+* @author Dave Bristor
+*/
+public class FOStorePMFFactory implements ObjectFactory {
+    
+    /**
+     * Uses StringRefAddr's to store the information
+     */
+    public Object getObjectInstance(
+        Object obj, Name name, Context ctx, Hashtable env) throws Exception {
+
+        FOStorePMF rc = null;
+
+        if (obj instanceof Reference) {
+            Reference ref = (Reference)obj;
+            if (ref.getClassName().equals(FOStorePMF.class.getName())) {
+                Properties p = new Properties();
+                for (Enumeration e = ref.getAll(); e.hasMoreElements();) {
+                    StringRefAddr sra = (StringRefAddr)e.nextElement();
+                    p.setProperty(sra.getType(), (String)sra.getContent());
+                }
+
+                rc = new FOStorePMF();
+                rc.setFromProperties(p);
+            }
+        }
+        return rc;
+    }
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreRemoteConnection.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreRemoteConnection.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreRemoteConnection.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreRemoteConnection.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+
+/*
+ * FOStoreRemoteClientImpl.java
+ *
+ * Created on June 18, 2001, 4:44 PM
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.net.URL;
+import java.net.Socket;
+
+import java.io.DataOutputStream;
+import java.io.DataOutput;
+import java.io.OutputStream;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.IOException;
+
+/**
+ * Represents a connection to a store that runs in a JVM separate from that of
+ * a client.
+ * <p>
+ * This class is <code>public</code> so that clients can access the value of
+ * <code>DEFAULT_PORT</code>.
+ *
+ * @author  Craig Russell
+ * @version 1.0
+ */
+public class FOStoreRemoteConnection extends FOStoreClientConnectionImpl {
+
+    /** The default port number
+     */
+    public final static int DEFAULT_PORT = 9919;
+    
+    /** The socket used to communicate with the remote server.
+     */    
+    private Socket socket;
+    
+    /** The DataInputStream from the socket for replies from the server.
+     */
+    private DataInput serverReplies;
+    
+    /** The DataOutputStream from the socket for requests for the server.
+     */
+    private DataOutputStream clientRequests;
+    
+    /** Creates new FOStoreRemoteConnection
+     * @param url the url of the server.
+     */
+    FOStoreRemoteConnection(URL url) {
+        super (url);
+    }
+
+    /** Connect to the data store.  The user name and password are stored in
+     * the connectionId.
+     * @throws IOException if a network error occurs
+     */    
+    public void connect() throws IOException {
+        String host = url.getHost();
+        int port = url.getPort();
+        if (port == -1)
+            port = DEFAULT_PORT;
+        if (logger.isDebugEnabled()) logger.debug("FOCCI:connect " +  // NOI18N
+            " Host: " + host + // NOI18N
+            " Port: " + port); // NOI18N
+        socket = new Socket (host, port);
+        // we are connected; now send our greeting (login).
+        login();
+    }
+    
+    /**
+     * Provides DataInput from which the client can read replies from
+     * the server.
+     * @return DataInput from which the client can read replies.
+     * @throws IOException if any problems.
+     */
+    public DataInput getInputFromServer() throws IOException {
+        if (serverReplies == null) {
+            serverReplies = new DataInputStream (socket.getInputStream());
+        }
+            return serverReplies;
+    }
+    
+    /** Write bytes to the store.  This is the only method to actually write
+     * data bytes from the Message to the server.  As soon as the remote side
+     * has read the bytes, it processes the message and sends the reply.
+     * @param buffer the data buffer
+     * @param offset the offset within the buffer
+     * @param length the number of bytes to write
+     * @throws IOException if any problems.
+     */
+    public void sendToStore (byte[] buffer, int offset, int length) throws IOException {
+        if (clientRequests == null) {
+            OutputStream os = socket.getOutputStream();
+            clientRequests = new DataOutputStream (os);
+        }
+        clientRequests.writeInt (length - offset); // receiver needs to allocate a buffer this big
+        clientRequests.write (buffer, offset, length);
+    }
+        
+    /** Close the database associated with this connection.  This closes the socket
+     * associated, which causes the remote database to be closed.
+     * @throws IOException if any problems with the socket.
+     * @throws FOStoreDatabaseException if any problems with the database (not used here).
+     */
+    public void closeDatabase() throws IOException, FOStoreDatabaseException {
+        socket.close();
+    }
+
+    /**
+     * @return The path as given, with the leading '/' removed if there is one.
+     */
+    protected String localizePath(String path) {
+        // Use the correct path, not what Java gives you (see RFC1738)
+        if (path.startsWith("/")) { // NOI18N
+            path = path.substring(1);
+        }
+        return path;
+    }
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreSchemaUID.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreSchemaUID.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreSchemaUID.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreSchemaUID.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,238 @@
+/*
+ * 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.DataInput;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.DigestOutputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import java.util.HashMap;
+
+import javax.jdo.JDOFatalInternalException;
+import javax.jdo.JDOUserException;
+import javax.jdo.JDOFatalUserException;
+import javax.jdo.spi.JDOImplHelper;
+import javax.jdo.spi.PersistenceCapable;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.util.I18NHelper;
+
+/**
+* A FOStoreSchemaUID is an internal name used to distinguish persistence
+* capable classes based on the structure of their persistent fields as
+* indicated by the enhancer.  This is very similar to, and the implementation
+* is based on, the process of computing a serialVersionUID as described in 
+* <a href="http://java.sun.com/products/jdk/1.2/docs/guide/serialization/spec/class.doc4.html"> Object Serialization Specification, Section 4.4, Stream Unique Identifiers</a>. // NOI18N
+*
+* @author Dave Bristor
+*/
+class FOStoreSchemaUID {
+    /** The 'value' of this FOStoreSchemaUID */
+    private final long fsuid;
+    
+    /** Map from ClassLoader to a HashMap that in turn maps from Class to
+    * FOStoreSchemaUID.
+    */
+    private static final HashMap loaderMap = new HashMap();
+
+    /** 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
+
+    private static final FOStoreSchemaUID NOT_PERSISTENT =
+        new FOStoreSchemaUID(0);
+
+    /** JDOImplHelper instance */
+    private static final JDOImplHelper helper = 
+        (JDOImplHelper) AccessController.doPrivileged (
+            new PrivilegedAction () {
+                public Object run () {
+                    try {
+                        return JDOImplHelper.getInstance();
+                    }
+                    catch (SecurityException e) {
+                        throw new JDOFatalUserException (msg.msg(
+                            e.getMessage()), e); // NOI18N
+                    }
+                }
+            }    
+        );
+
+    private FOStoreSchemaUID(long value) {
+        this.fsuid = value;
+    }
+    
+    private FOStoreSchemaUID(Class cls) {
+        this.fsuid = computeUID(cls);
+    }
+
+    /** Provides a FOStoreSchemaUID corresponding to the given class.  Any
+     *  class which
+     * <ul>
+     * <li>implements PersistenceCapable and</li>
+     * <li>is itself enhanced</li>
+     *</ul>
+     * has a distinct FOStoreSchemaUID.  All other classes share a common
+     * FOStoreSchemaUID. (A class can be PersistenceCapable but not enhanced
+     * by virtue of being in an inheritance chain, in which a class which does
+     * not have a JDO model inherits a class that does have a JDO model.)
+     * <em>This should only be invoked by client code, never by server code,
+     * because it involves client-side concepts such as
+     * PersistenceCapable.</em> 
+    * @param cls Class for which a FOStoreSchemaUID is needed.
+    * @param model FOStoreModel for determining whether cls was enhanced.
+    * @return FOStoreSchemaUID corresponding to given Class.
+    */
+    static synchronized FOStoreSchemaUID lookup(Class cls, FOStoreModel model) {
+        FOStoreSchemaUID rc = null;
+        if (! PersistenceCapable.class.isAssignableFrom(cls) ||
+               model.getJDOClass(cls) == null) {
+            rc = NOT_PERSISTENT;
+        } else {        
+            HashMap classMap = (HashMap)loaderMap.get(cls.getClassLoader());
+            if (null == classMap) {
+                rc = new FOStoreSchemaUID(cls);
+                classMap = new HashMap();
+                classMap.put(cls, rc);
+                loaderMap.put(cls.getClassLoader(), classMap);
+            } else {
+                rc = (FOStoreSchemaUID)classMap.get(cls);
+                if (null == rc) {
+                    rc = new FOStoreSchemaUID(cls);
+                    classMap.put(cls, rc);
+                }
+            }
+        }
+        return rc;
+    }
+
+    private long computeUID(Class cls) {
+        long rc = 0;
+        try {
+            MessageDigest md = MessageDigest.getInstance("SHA"); // NOI18N
+            ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
+            DigestOutputStream mdo = new DigestOutputStream(baos, md);
+            DataOutputStream data = new DataOutputStream(mdo);
+
+            computeUID(cls, data);
+     
+            // Compute the hash value for cls
+            data.flush();
+            byte hasharray[] = md.digest();
+            for (int i = 0; i < Math.min(8, hasharray.length); i++) {
+                rc += (long)(hasharray[i] & 255) << (i * 8);
+            }
+            
+        } catch (IOException ex) {
+            // Can't happen, but be deterministic anyway
+            rc = -1;
+        } catch (NoSuchAlgorithmException ex) {
+            throw new JDOFatalInternalException(
+                msg.msg("ERR_Algorithm"), ex); // NOI18N
+        }
+        return rc;
+    }
+
+    private void computeUID(Class cls, DataOutputStream out)
+        throws IOException {
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("FSUID.computeUID: " + cls.getName()); // NOI18N
+        }
+        
+        out.writeUTF(cls.getName());
+
+        // We don't need to sort these as the enhancer will have done that.
+        String names[] = helper.getFieldNames(cls);
+        Class types[] = helper.getFieldTypes(cls);
+        byte flags[] = helper.getFieldFlags(cls);
+        int length = names.length;
+
+        for (int i = 0; i < length; i++) {
+            out.writeUTF(names[i]);
+            out.writeUTF(types[i].getName());
+            out.writeByte(flags[i]);
+        }
+
+        Class spr = helper.getPersistenceCapableSuperclass(cls);
+        if (null != spr) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("FSUID: spr for " + cls.getName() + // NOI18N
+                           " is " + cls.getName()); // NOI18N
+            }
+            computeUID(spr, out);
+        }
+    }
+
+    public String toString() {
+        return "" + this.fsuid; // NOI18N
+    }
+
+    //
+    // Support for I/O
+    //
+
+    void write(DataOutput out) throws IOException {
+        out.writeLong(fsuid);
+    }
+
+    static FOStoreSchemaUID read(DataInput in) throws IOException {
+        return new FOStoreSchemaUID(in.readLong());
+    }
+
+    //
+    // Support for equality
+    //
+
+    public boolean equals(Object o) {
+        boolean rc = false;
+        if ((null != o) && (o instanceof FOStoreSchemaUID)) {
+            rc = (fsuid == ((FOStoreSchemaUID)o).fsuid);
+        }
+        return rc;
+    }
+
+    /**
+     * Computes a hashcode for this FOStoreSchemaUID. The result is the
+     * exclusive OR of the two halves of the primitive <code>long</code>
+     * value represented by this <code>Long</code> object. That is, the
+     * hashcode is the value of the expression:
+     * <blockquote><pre>
+     * (int)(this.longValue()^(this.longValue()>>>32))
+     * </pre></blockquote>
+     * This is the same algoritm as is used for java.lang.Long.
+     *
+     * @return  a hash code value for this object.
+     */
+    public int hashCode() {
+        // Same as for java.lang.Long
+        return (int)(fsuid ^ (fsuid >> 32));
+    }
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreServerConnection.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreServerConnection.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreServerConnection.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreServerConnection.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,115 @@
+/*
+ * 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;
+
+/**
+* A connection as used by a server/store.  It provides a means of getting the
+* client's input, and of writing reply data back to the client.
+*
+* @author Dave Bristor
+*/
+interface FOStoreServerConnection extends FOStoreConnection {
+    /**
+    * Provides a DataInput from which the server can read the client's
+    * requests.
+    * @return DataInput for reading requests.
+    */
+    public FOStoreInput getInputFromClient();
+
+    /**
+    * Provides a DataOutput to which the server can write data for the
+    * client.  This is not normally used for writing data associated with a
+    * single reply (use createReply for that purpose).
+    * @return FOStoreOutput for writing data to client.
+    */
+    public FOStoreOutput getOutputForClient();
+
+    /**
+    * Provides a Reply to which the server can write replies to the
+    * client's requests.
+    * @return Reply object for writing information about one reply.
+    */
+    public Reply createReply(RequestId requestId) throws IOException;
+
+    /**
+    * Adds the extent to this connections set of extents that have been
+    * changed during a transaction.
+    */
+    public boolean addExtent(DBExtent dbExtent);
+
+    /**
+    * Commits the work done in this connection.
+    */
+    public void commit() throws FOStoreDatabaseException;
+
+    /**
+    * Rolls back the work done in this connection.
+    */
+    public void rollback() throws FOStoreDatabaseException;
+
+    /**
+    * Sends all the reply data to the client.
+    */
+    public void sendToClient() throws IOException, FOStoreDatabaseException;
+
+    /**
+    * Provides the database to be used by the server using this connection.
+    * @return A database.
+    */
+    public FOStoreDatabase getDatabase();
+    
+    /** Set client data stream.  Only used in local case.
+     */
+    public void setClientInput (FOStoreInput in) throws IOException;
+    
+    /** Process requests from client.
+     */
+    public void processRequests ();
+    
+    /** Log in to the database.
+     */
+    public void openDatabase(String dbname, String user, long timestamp, byte[] secret, boolean create)
+        throws java.lang.InterruptedException, FOStoreDatabaseException;
+    
+    /** Provide the output from the server to the client reply handler.
+     */
+    public DataInput getOutputFromServer();
+    
+    /** Write the output from the server to the socket
+     */
+    public void writeOutputToClient() throws IOException;
+    
+    /** Read the input stream from the socket.
+     */
+    public void readInputFromClient() throws IOException;
+
+    /** Close the database.  Each open connection will perform this operation;
+     * only the last open connection to be closed will actually close the 
+     * database.
+     */
+    public void closeDatabase() throws FOStoreDatabaseException;
+
+    /** Indicates whether or not it is OK to release a database after a
+     * message's contents are processed.
+     */
+    // XXX TBD The server connection and implementation  needs refactoring
+    public void setOkToReleaseDatabase(boolean ok);
+}

Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreServerConnectionImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreServerConnectionImpl.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreServerConnectionImpl.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreServerConnectionImpl.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,355 @@
+/*
+ * 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.
+ */
+
+/*
+ * FOStoreServerConnectionImpl.java
+ *
+ * Created on June 7, 2001, 3:16 PM
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.DataInput;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import java.net.Socket;
+
+import java.util.HashSet;
+import java.util.Iterator;
+
+import javax.jdo.JDOFatalInternalException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.util.I18NHelper;
+
+/**
+ *
+ * @author  Craig Russell
+ * @version 1.0
+ */
+
+ /** This class implements the FOStoreServerConnection contract.  It is used
+  * in two modes: local and remote.  In local mode, the default constructor
+  * is used.  In remote mode, the constructor that takes a Socket is used.
+  * The connection after construction does not contain any information about
+  * the data store.  After the login request is successfully executed, the
+  * Database information is known.  Subsequent requests know the Database.
+  */
+// XXX This class needs to be split into 2: one which handles the
+// socket-connected case, the other which handles the local case.
+class FOStoreServerConnectionImpl implements FOStoreServerConnection {
+
+    /** 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
+    
+    /** Used by server to write its replies.
+     */
+    private FOStoreOutput serverData = new FOStoreOutput();
+
+    /** Used by server to read client's requests.
+     */
+    private FOStoreInput clientDataInput;
+
+    /** The socket over which we communicate to the client.
+     */
+    private final Socket socket;
+
+    /** Root in filesystem at which database will be created.
+     */
+    private final String root;
+    
+    /** The input stream from the socket.  Set after connect; reset at
+     * socket.close().
+     */
+    private DataInputStream socketDataInputStream = null;
+    
+    /** The output stream from the socket.  Set after connect; reset at
+     * socket.close().
+     */
+    private OutputStream socketOutputStream = null;
+
+    /** The local database name.
+     */
+    private String dbname;
+    
+    /** The local database
+     */    
+    private FOStoreDatabase fodb;
+
+    /** Indicates if releaseDatabase can really do so.
+     */
+    private boolean okToReleaseDatabase = true;
+    
+    /** Creates new FOStoreServerConnectionImpl for the local case.
+     */
+    public FOStoreServerConnectionImpl() {
+        this.socket = null;
+        this.root = null;
+    }
+
+    /** Creates new FOStoreServerConnectionImpl for the remote case.
+     */
+    public FOStoreServerConnectionImpl(Socket socket, String root) {
+        this.socket = socket;
+        this.root = root;
+    }
+
+    /**
+     * Commits the work done in this connection.  The database must already
+     * be connected.  Stores in the database (a) the extents that have been
+     * changed and (b) the database's DBInfo. 
+     */
+    public void commit() throws FOStoreDatabaseException {
+        if (logger.isDebugEnabled()) logger.debug("FOSCI.commit"); // NOI18N
+        FOStoreDatabase db = getDatabase();
+
+        DBInfo dbInfo = db.getDBInfo();
+        dbInfo.storeDirtyExtents();
+        dbInfo.store();
+        db.commitChanges();
+    }
+    
+    /**
+     * Rolls back the work done in this connection.
+     */
+    public void rollback() throws FOStoreDatabaseException {
+        FOStoreDatabase db = getDatabase();
+        db.getDBInfo().clearDirtyExtents();
+        db.rollbackChanges();
+    }
+    
+    /**
+     * Provides a Reply to which the server can write replies to the
+     * client's requests.
+     * @return Reply object for writing information about one reply.
+     */
+    public Reply createReply(RequestId requestId) throws IOException {
+        return new Reply(requestId, serverData);
+    }
+    
+    /**
+     * Provides a DataInput from which the server can read the client's
+     * requests.
+     * @return DataInput for reading requests.
+     */
+    public FOStoreInput getInputFromClient() {
+        return clientDataInput;
+    }
+    
+    public void readInputFromClient() throws IOException {
+        if (socketDataInputStream == null) {
+            InputStream is = socket.getInputStream();
+            socketDataInputStream = new DataInputStream (is);
+        }
+        if (logger.isDebugEnabled()) {
+            logger.debug (
+                "FOSCI.readInputFromClient available: " + // NOI18N
+                socketDataInputStream.available());
+        }
+
+        int length = socketDataInputStream.readInt();
+        byte[] buffer = new byte[length];
+        socketDataInputStream.readFully(buffer);
+        setClientInput( new FOStoreInput (buffer, 0, length));
+    }
+    
+    /**
+     * @see FOStoreServerConnection#sendToClient
+     */
+    public void sendToClient() throws IOException, FOStoreDatabaseException {
+    }
+    
+    /**
+     * Adds the extent to this connections set of extents that have been
+     * changed during a transaction.  They will be put to the database when
+     * sendToClient is invoked.
+     */
+    public boolean addExtent(DBExtent dbExtent) {
+        boolean rc = getDatabase().getDBInfo().makeExtentDirty(dbExtent);
+        if (logger.isDebugEnabled()) {
+            logger.debug("FOSCI.addExtent to: " + this + // NOI18N
+                           " dbExtent: " + dbExtent + // NOI18N
+                           "add rc: "  + rc); // NOI18N
+        }
+        return rc;
+    }
+    
+    /** Open the database if it exists, and verify the user authentication.
+     * If the database does not exist, create it.
+     */
+    public void openDatabase (String dbname, String user, long timestamp,
+                              byte[] secret, boolean create) 
+        throws FOStoreDatabaseException, InterruptedException {
+        
+        if (logger.isDebugEnabled()) {
+            logger.debug("FOSCI.openDatabase " + dbname +  // NOI18N
+            " user: " + user); // NOI18N
+        }
+
+        fodb = FOStoreDatabase.getDatabase(databasePath(dbname), create);
+        this.dbname = dbname;
+        fodb.verifyUserPassword(user, timestamp, secret);
+    }
+
+    /**
+     * Provides the database to be used by the server using this connection.
+     * @return A database.
+     */
+    public FOStoreDatabase getDatabase() {
+        try {
+            if (fodb == null) {
+                 fodb = FOStoreDatabase.getDatabase(
+                     databasePath(dbname), false);
+            }
+            return fodb;
+        } catch (InterruptedException ex) {
+            throw new JDOFatalInternalException(
+                msg.msg("ERR_GetDatabaseInterrupted"), ex); // NOI18N
+        } catch (FOStoreDatabaseException ex) {
+            throw new JDOFatalInternalException(
+                msg.msg("ERR_GetDatabaseException"), ex); // NOI18N
+        }
+    }
+        
+    /**
+     * Provides a DataOutput to which the server can write data for the
+     * client.  This is not normally used for writing data associated with a
+     * single reply (use createReply for that purpose).
+     * @return FOStoreOutput for writing data to client.
+     */
+    public FOStoreOutput getOutputForClient() {
+        return serverData;
+    }
+    
+    /** Provides a DataInput from which the local client can read the server's
+     * replies.  Reset for the next output request.
+     */
+    public DataInput getOutputFromServer() {
+        DataInput di = new DataInputStream(
+            new ByteArrayInputStream(
+                serverData.getBuf(), 0, serverData.getPos()));
+        
+        serverData.reset(); // reset the output stream
+        return di;
+    }
+    
+    /** Writes the output to the client socket.  Reset for the next output
+     * request. 
+     */
+    public void writeOutputToClient() throws IOException {
+        if (socketOutputStream == null) {
+            if (logger.isDebugEnabled()) {
+                logger.debug(
+                    "FOSCI.writeOutputToClient getting socketOutputStream"); // NOI18N
+            }
+
+            socketOutputStream = socket.getOutputStream();
+            if (logger.isDebugEnabled()) {
+                logger.debug(
+                    "FOSCI.writeOutputToClient got socketOutputStream"); // NOI18N
+            }
+        }
+        
+        if (logger.isDebugEnabled()) {
+            logger.debug(
+                "FOSCI.writeOutputToClient writing socketOutputStream: " + // NOI18N
+                serverData.getPos() + " bytes"); // NOI18N
+        }
+
+        socketOutputStream.write(serverData.getBuf(), 0, serverData.getPos());
+        serverData.reset(); // reset the output stream
+    }
+    
+    public void setClientInput (FOStoreInput fi) {
+        clientDataInput = fi;
+    }
+    
+    public void processRequests() {
+        RequestHandler.handleRequests(this);
+    }
+    
+    /** Indicates whether or not releaseDatabase can actually release the
+     * database.
+     */
+    public void setOkToReleaseDatabase(boolean ok) {
+        if (logger.isDebugEnabled()) {
+            logger.debug("FOSCI.setOk: " + ok); // NOI18N
+        }
+        this.okToReleaseDatabase = ok;
+    }
+    
+    /** Release the database associated with this connection.
+     */
+    void releaseDatabase() throws InterruptedException {
+        if (okToReleaseDatabase && fodb != null) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("FOSCI.releaseDatabase: releasing"); // NOI18N
+            }
+            FOStoreDatabase.releaseDatabase(fodb);
+            fodb = null;
+        }
+    }
+
+    /** Close the database associated with this connection.
+     */
+    public void closeDatabase() throws FOStoreDatabaseException {
+        try {
+            if (logger.isDebugEnabled()) {
+                logger.debug("FOSCI.closeDatabase " + dbname); // NOI18N
+            }
+            releaseDatabase();
+            FOStoreDatabase.closeDatabase(databasePath(dbname));
+        } catch (InterruptedException ex) {
+            throw new JDOFatalInternalException(
+            msg.msg("ERR_CloseDatabaseInterrupted"), ex); // NOI18N
+        }
+    }
+    
+    /** Close this connection; release all resources.
+     */
+    public void close() throws FOStoreDatabaseException {
+        if (logger.isDebugEnabled()) {
+            logger.debug("FOSCI.close " + dbname); // NOI18N
+        }
+        closeDatabase();
+    }
+
+    /** @return A String for the databse's pathnamne.  It is based on the
+    * given dbname, plus the root, if one was given when this connection was
+    * created.
+    */
+    private final String databasePath(String dbname) {
+        String rc;
+        if (null == root) {
+            rc = dbname;
+        } else {
+            rc = root + File.separator + dbname;
+        }
+        return rc;
+    }
+}



Mime
View raw message