You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pc...@apache.org on 2006/07/19 23:35:07 UTC

svn commit: r423615 [3/44] - in /incubator/openjpa/trunk: ./ openjpa-jdbc-5/ openjpa-jdbc-5/src/ openjpa-jdbc-5/src/main/ openjpa-jdbc-5/src/main/java/ openjpa-jdbc-5/src/main/java/org/ openjpa-jdbc-5/src/main/java/org/apache/ openjpa-jdbc-5/src/main/j...

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/MappingRepositoryValue.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/package.html
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/package.html?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/package.html (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/package.html Wed Jul 19 14:34:44 2006
@@ -0,0 +1,9 @@
+<html>
+<body>
+<p><strong>OpenJPA-JDBC Configuration</strong></p>
+
+<p>
+    This package provides JDBC configuration interfaces.
+</p>
+</body>
+</html>

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/package.html
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSavepointManager.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSavepointManager.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSavepointManager.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSavepointManager.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2006 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.openjpa.jdbc.kernel;
+
+import java.sql.Connection;
+import java.util.Collection;
+
+import org.apache.openjpa.conf.OpenJPAConfiguration;
+import org.apache.openjpa.kernel.Broker;
+import org.apache.openjpa.kernel.OpenJPASavepoint;
+import org.apache.openjpa.kernel.RestoreState;
+import org.apache.openjpa.kernel.SavepointManager;
+import org.apache.openjpa.lib.conf.Configurable;
+import org.apache.openjpa.lib.conf.Configuration;
+
+/**
+ * Abstract {@link SavepointManager} implementation that
+ * delegates to the subclass for savepoint operations on the active
+ * {@link Connection}. This implementation issues a flush and relies
+ * on the driver/db to restore back to the flushed state.
+ *
+ * @author Steve Kim
+ * @since 3.4
+ */
+public abstract class AbstractJDBCSavepointManager
+    implements SavepointManager, Configurable {
+
+    private boolean _restore = false;
+
+    public void startConfiguration() {
+    }
+
+    public void setConfiguration(Configuration conf) {
+        _restore = ((OpenJPAConfiguration) conf).getRestoreStateConstant()
+            != RestoreState.RESTORE_NONE;
+    }
+
+    public void endConfiguration() {
+    }
+
+    /**
+     * Return whether to retain in-memory copies of field values for restore
+     * on rollback. Defaults to {@link OpenJPAConfiguration#getRestoreState).
+     */
+    public boolean getRestoreFieldState() {
+        return _restore;
+    }
+
+    /**
+     * Set whether to retain in-memory copies of field values for restore
+     * on rollback. Defaults to {@link OpenJPAConfiguration#getRestoreState}.
+     */
+    public void setRestoreFieldState(boolean restore) {
+        _restore = restore;
+    }
+
+    public OpenJPASavepoint newSavepoint(String name, Broker broker) {
+        // flush after creating savepoint b/c flush may add/change states
+        OpenJPASavepoint save = new ConnectionSavepoint(broker, name, _restore);
+        broker.flush();
+        return save;
+    }
+
+    public boolean supportsIncrementalFlush() {
+        return true;
+    }
+
+    /**
+     * Rollback the datastore savepoint.
+     */
+    protected abstract void rollbackDataStore(ConnectionSavepoint savepoint);
+
+    /**
+     * Set the datastore savepoint.
+     */
+    protected abstract void setDataStore(ConnectionSavepoint savepoint);
+
+    /**
+     * A savepoint which provides access to the current transactional
+     * connection.
+     */
+    protected class ConnectionSavepoint extends OpenJPASavepoint {
+
+        private Object _savepoint;
+
+        public ConnectionSavepoint(Broker broker, String name, boolean copy) {
+            super(broker, name, copy);
+        }
+
+        /**
+         * Return the stored savepoint object
+         */
+        public Object getDataStoreSavepoint() {
+            return _savepoint;
+        }
+
+        /**
+         * Set the implementation specific savepoint object
+         */
+        public void setDataStoreSavepoint(Object savepoint) {
+            _savepoint = savepoint;
+        }
+
+        /**
+         * Return the current {@link Connection} for this savepoint.
+         */
+        public Connection getConnection() {
+            return ((JDBCStoreManager) getBroker().getStoreManager().
+                getInnermostDelegate()).getConnection();
+        }
+
+        public Collection rollback(Collection previous) {
+            AbstractJDBCSavepointManager.this.rollbackDataStore(this);
+            return super.rollback(previous);
+        }
+
+        public void save(Collection states) {
+            AbstractJDBCSavepointManager.this.setDataStore(this);
+            super.save(states);
+        }
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSavepointManager.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSeq.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSeq.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSeq.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSeq.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2006 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.openjpa.jdbc.kernel;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import javax.sql.DataSource;
+
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.schema.SchemaGroup;
+import org.apache.openjpa.jdbc.sql.SQLExceptions;
+import org.apache.openjpa.kernel.StoreContext;
+import org.apache.openjpa.meta.ClassMetaData;
+import org.apache.openjpa.util.OpenJPAException;
+import org.apache.openjpa.util.StoreException;
+
+/**
+ * Abstract sequence implementation. Handles obtaining the proper
+ * connection to used based on whether the sequence is transactional and
+ * whether a second datasource is configured.
+ *
+ * @author Abe White
+ */
+public abstract class AbstractJDBCSeq
+    implements JDBCSeq {
+
+    protected int type = TYPE_DEFAULT;
+    protected Object current = null;
+
+    // used to track current conn so that we can close it
+    private Connection _conn = null;
+    private boolean _commit = false;
+
+    /**
+     * Records the sequence type.
+     */
+    public void setType(int type) {
+        this.type = type;
+    }
+
+    public synchronized Object next(StoreContext ctx, ClassMetaData meta) {
+        JDBCStore store = getStore(ctx);
+        try {
+            current = nextInternal(store, (ClassMapping) meta);
+            return current;
+        } catch (OpenJPAException ke) {
+            throw ke;
+        } catch (SQLException se) {
+            throw SQLExceptions.getStore(se, store.getDBDictionary());
+        } catch (Exception e) {
+            throw new StoreException(e);
+        } finally {
+            closeConnection();
+        }
+    }
+
+    public synchronized Object current(StoreContext ctx, ClassMetaData meta) {
+        JDBCStore store = getStore(ctx);
+        try {
+            return currentInternal(store, (ClassMapping) meta);
+        } catch (OpenJPAException ke) {
+            throw ke;
+        } catch (SQLException se) {
+            throw SQLExceptions.getStore(se, store.getDBDictionary());
+        } catch (Exception e) {
+            throw new StoreException(e);
+        } finally {
+            closeConnection();
+        }
+    }
+
+    public synchronized void allocate(int additional, StoreContext ctx,
+        ClassMetaData meta) {
+        JDBCStore store = getStore(ctx);
+        try {
+            allocateInternal(additional, store, (ClassMapping) meta);
+        } catch (OpenJPAException ke) {
+            throw ke;
+        } catch (SQLException se) {
+            throw SQLExceptions.getStore(se, store.getDBDictionary());
+        } catch (Exception e) {
+            throw new StoreException(e);
+        } finally {
+            closeConnection();
+        }
+    }
+
+    /**
+     * No-op.
+     */
+    public void addSchema(ClassMapping mapping, SchemaGroup group) {
+    }
+
+    /**
+     * No-op.
+     */
+    public void close() {
+    }
+
+    /**
+     * Return the next sequence object.
+     */
+    protected abstract Object nextInternal(JDBCStore store,
+        ClassMapping mapping)
+        throws Exception;
+
+    /**
+     * Return the current sequence object. By default returns the last
+     * sequence value used, or null if no sequence values have been requested
+     * yet.
+     */
+    protected Object currentInternal(JDBCStore store, ClassMapping mapping)
+        throws Exception {
+        return current;
+    }
+
+    /**
+     * Allocate additional sequence values. Does nothing by default.
+     */
+    protected void allocateInternal(int additional, JDBCStore store,
+        ClassMapping mapping)
+        throws Exception {
+    }
+
+    /**
+     * Extract the store from the given context.
+     */
+    private JDBCStore getStore(StoreContext ctx) {
+        return (JDBCStore) ctx.getStoreManager().getInnermostDelegate();
+    }
+
+    /**
+     * Return the connection to use based on the type of sequence. This
+     * connection will automatically be closed; do not close it.
+     */
+    protected Connection getConnection(JDBCStore store)
+        throws SQLException {
+        // close previous connection if user is asking for another connection
+        closeConnection();
+
+        if (type == TYPE_TRANSACTIONAL || type == TYPE_CONTIGUOUS)
+            _conn = store.getConnection();
+        else {
+            JDBCConfiguration conf = store.getConfiguration();
+            DataSource ds = conf.getDataSource2(store.getContext());
+            _conn = ds.getConnection();
+            if (_conn.getAutoCommit())
+                _conn.setAutoCommit(false);
+            _commit = true;
+        }
+        return _conn;
+    }
+
+    /**
+     * Close the current connection.
+     */
+    protected void closeConnection() {
+        if (_conn == null)
+            return;
+
+        try {
+            if (_commit)
+                _conn.commit();
+        } catch (SQLException se) {
+            throw SQLExceptions.getStore(se);
+        } finally {
+            try {
+                _conn.close();
+            } catch (SQLException se) {
+            }
+            _conn = null;
+            _commit = false;
+        }
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSeq.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,384 @@
+/*
+ * Copyright 2006 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.openjpa.jdbc.kernel;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.BitSet;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.Discriminator;
+import org.apache.openjpa.jdbc.meta.FieldMapping;
+import org.apache.openjpa.jdbc.meta.Strategy;
+import org.apache.openjpa.jdbc.meta.Version;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.jdbc.sql.RowManager;
+import org.apache.openjpa.jdbc.sql.SQLExceptions;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.kernel.PCState;
+import org.apache.openjpa.lib.conf.Configurable;
+import org.apache.openjpa.lib.conf.Configuration;
+import org.apache.openjpa.util.OpenJPAException;
+import org.apache.openjpa.util.OptimisticException;
+
+/**
+ * Base update manager with common functionality.
+ *
+ * @author Abe White
+ */
+public abstract class AbstractUpdateManager
+    implements UpdateManager, Configurable {
+
+    protected JDBCConfiguration conf = null;
+    protected DBDictionary dict = null;
+
+    public void setConfiguration(Configuration conf) {
+        this.conf = (JDBCConfiguration) conf;
+        dict = this.conf.getDBDictionaryInstance();
+    }
+
+    public void startConfiguration() {
+    }
+
+    public void endConfiguration() {
+    }
+
+    public Collection flush(Collection states, JDBCStore store) {
+        Connection conn = store.getConnection();
+        try {
+            PreparedStatementManager psMgr = newPreparedStatementManager
+                (store, conn);
+            return flush(states, store, psMgr);
+        } finally {
+            try {
+                conn.close();
+            } catch (SQLException se) {
+            }
+        }
+    }
+
+    private Collection flush(Collection states, JDBCStore store,
+        PreparedStatementManager psMgr) {
+        // run through all the states and update them as necessary
+        RowManager rowMgr = newRowManager();
+        Collection customs = new LinkedList();
+        Collection exceps = null;
+        for (Iterator itr = states.iterator(); itr.hasNext();)
+            exceps =
+                populateRowManager((OpenJPAStateManager) itr.next(), rowMgr,
+                    store, exceps, customs);
+
+        // flush rows
+        exceps = flush(rowMgr, psMgr, exceps);
+
+        // now do any custom mappings
+        for (Iterator itr = customs.iterator(); itr.hasNext();) {
+            try {
+                ((CustomMapping) itr.next()).execute(store);
+            } catch (SQLException se) {
+                exceps = addException(exceps, SQLExceptions.getStore(se,
+                    dict));
+            } catch (OpenJPAException ke) {
+                exceps = addException(exceps, ke);
+            }
+        }
+
+        // return all exceptions
+        Collection psExceps = psMgr.getExceptions();
+        if (exceps == null)
+            return psExceps;
+        if (psExceps == null)
+            return exceps;
+        exceps.addAll(psExceps);
+        return exceps;
+    }
+
+    /**
+     * Return a new {@link RowManager}.
+     */
+    protected abstract RowManager newRowManager();
+
+    /**
+     * Return a new {@link PreparedStatementManager}.
+     */
+    protected abstract PreparedStatementManager newPreparedStatementManager
+        (JDBCStore store, Connection conn);
+
+    /**
+     * Flush all rows of the given row manager. Add exceptions to
+     * <code>exceps</code> (which may start as null) using
+     * {@link #addException}. Return <code>exceps</code>.
+     */
+    protected abstract Collection flush(RowManager rowMgr,
+        PreparedStatementManager psMgr, Collection exceps);
+
+    /**
+     * Populate the row manager with rows to be flushed for the given state.
+     *
+     * @param exceps exceptions encountered when flushing will be added to
+     * this list and returned; the list may be null initially
+     * @param customs buffer custom mappings
+     * @return the exceptions list
+     */
+    private Collection populateRowManager(OpenJPAStateManager sm,
+        RowManager rowMgr, JDBCStore store, Collection exceps,
+        Collection customs) {
+        try {
+            if (sm.getPCState() == PCState.PNEW && !sm.isFlushed()) {
+                insert(sm, (ClassMapping) sm.getMetaData(), rowMgr,
+                    store, customs);
+            } else if (sm.getPCState() == PCState.PNEWFLUSHEDDELETED
+                || sm.getPCState() == PCState.PDELETED) {
+                delete(sm, (ClassMapping) sm.getMetaData(), rowMgr,
+                    store, customs);
+            } else if ((sm.getPCState() == PCState.PDIRTY
+                && (!sm.isFlushed() || sm.isFlushedDirty()))
+                || (sm.getPCState() == PCState.PNEW
+                && sm.isFlushedDirty())) {
+                BitSet dirty = sm.getDirty();
+                if (sm.isFlushed()) {
+                    dirty = (BitSet) dirty.clone();
+                    dirty.andNot(sm.getFlushed());
+                }
+
+                if (dirty.length() > 0)
+                    update(sm, dirty, (ClassMapping) sm.getMetaData(),
+                        rowMgr, store, customs);
+            } else if (sm.isVersionUpdateRequired()) {
+                updateIndicators(sm, (ClassMapping) sm.getMetaData(),
+                    rowMgr, store, customs, true);
+            } else if (sm.isVersionCheckRequired()) {
+                if (!((ClassMapping) sm.getMetaData()).getVersion().
+                    checkVersion(sm, store, false))
+                    exceps = addException(exceps, new OptimisticException
+                        (sm.getManagedInstance()));
+            }
+        }
+        catch (SQLException se) {
+            exceps = addException(exceps, SQLExceptions.getStore(se, dict));
+        } catch (OpenJPAException ke) {
+            exceps = addException(exceps, ke);
+        }
+        return exceps;
+    }
+
+    /**
+     * Add the given exception to the given list, which may start out as null.
+     */
+    protected Collection addException(Collection exceps, Exception err) {
+        if (exceps == null)
+            exceps = new LinkedList();
+        exceps.add(err);
+        return exceps;
+    }
+
+    /**
+     * Recursive method to insert the given instance, base class first.
+     */
+    private void insert(OpenJPAStateManager sm, ClassMapping mapping,
+        RowManager rowMgr, JDBCStore store, Collection customs)
+        throws SQLException {
+        Boolean custom = mapping.isCustomInsert(sm, store);
+        if (!Boolean.FALSE.equals(custom))
+            mapping.customInsert(sm, store);
+        if (custom.equals(Boolean.TRUE))
+            return;
+
+        ClassMapping sup = mapping.getJoinablePCSuperclassMapping();
+        if (sup != null)
+            insert(sm, sup, rowMgr, store, customs);
+
+        mapping.insert(sm, store, rowMgr);
+        FieldMapping[] fields = mapping.getDefinedFieldMappings();
+        BitSet dirty = sm.getDirty();
+        for (int i = 0; i < fields.length; i++) {
+            if (dirty.get(fields[i].getIndex())
+                && !bufferCustomInsert(fields[i], sm, store, customs))
+                fields[i].insert(sm, store, rowMgr);
+        }
+        if (sup == null) {
+            Version vers = mapping.getVersion();
+            if (!bufferCustomInsert(vers, sm, store, customs))
+                vers.insert(sm, store, rowMgr);
+            Discriminator dsc = mapping.getDiscriminator();
+            if (!bufferCustomInsert(dsc, sm, store, customs))
+                dsc.insert(sm, store, rowMgr);
+        }
+    }
+
+    /**
+     * If the given mapping uses a custom insert, places a
+     * {@link CustomMapping} struct for it in the given collection and
+     * returns true, else returns false.
+     */
+    private boolean bufferCustomInsert(Strategy strat, OpenJPAStateManager sm,
+        JDBCStore store, Collection customs) {
+        Boolean custom = strat.isCustomInsert(sm, store);
+        if (!Boolean.FALSE.equals(custom))
+            customs.add(new CustomMapping(CustomMapping.INSERT, sm, strat));
+        return Boolean.TRUE.equals(custom);
+    }
+
+    /**
+     * Recursive method to delete the given instance, base class last.
+     */
+    private void delete(OpenJPAStateManager sm, ClassMapping mapping,
+        RowManager rowMgr, JDBCStore store, Collection customs)
+        throws SQLException {
+        Boolean custom = mapping.isCustomDelete(sm, store);
+        if (!Boolean.FALSE.equals(custom))
+            mapping.customDelete(sm, store);
+        if (Boolean.TRUE.equals(custom))
+            return;
+
+        FieldMapping[] fields = mapping.getDefinedFieldMappings();
+        for (int i = 0; i < fields.length; i++)
+            if (!bufferCustomDelete(fields[i], sm, store, customs))
+                fields[i].delete(sm, store, rowMgr);
+
+        ClassMapping sup = mapping.getJoinablePCSuperclassMapping();
+        if (sup == null) {
+            Version vers = mapping.getVersion();
+            if (!bufferCustomDelete(vers, sm, store, customs))
+                vers.delete(sm, store, rowMgr);
+            Discriminator dsc = mapping.getDiscriminator();
+            if (!bufferCustomDelete(dsc, sm, store, customs))
+                dsc.delete(sm, store, rowMgr);
+        }
+        mapping.delete(sm, store, rowMgr);
+
+        if (sup != null)
+            delete(sm, sup, rowMgr, store, customs);
+    }
+
+    /**
+     * @see #bufferCustomInsert
+     */
+    private boolean bufferCustomDelete(Strategy strat, OpenJPAStateManager sm,
+        JDBCStore store, Collection customs) {
+        Boolean custom = strat.isCustomDelete(sm, store);
+        if (!Boolean.FALSE.equals(custom))
+            customs.add(new CustomMapping(CustomMapping.DELETE, sm, strat));
+        return Boolean.TRUE.equals(custom);
+    }
+
+    /**
+     * Recursive method to update the given instance.
+     */
+    private void update(OpenJPAStateManager sm, BitSet dirty,
+        ClassMapping mapping, RowManager rowMgr, JDBCStore store,
+        Collection customs)
+        throws SQLException {
+        Boolean custom = mapping.isCustomUpdate(sm, store);
+        if (!Boolean.FALSE.equals(custom))
+            mapping.customUpdate(sm, store);
+        if (Boolean.TRUE.equals(custom))
+            return;
+
+        // update all fields before all mappings so that the mappings can
+        // detect whether any fields in their rows have been modified
+        FieldMapping[] fields = mapping.getDefinedFieldMappings();
+        for (int i = 0; i < fields.length; i++) {
+            if (dirty.get(fields[i].getIndex())
+                && !bufferCustomUpdate(fields[i], sm, store, customs))
+                fields[i].update(sm, store, rowMgr);
+        }
+
+        ClassMapping sup = mapping.getJoinablePCSuperclassMapping();
+        if (sup == null)
+            updateIndicators(sm, mapping, rowMgr, store, customs, false);
+        else
+            update(sm, dirty, sup, rowMgr, store, customs);
+        mapping.update(sm, store, rowMgr);
+    }
+
+    /**
+     * Update version and discriminator indicators.
+     */
+    private void updateIndicators(OpenJPAStateManager sm, ClassMapping mapping,
+        RowManager rowMgr, JDBCStore store, Collection customs,
+        boolean versionUpdateOnly)
+        throws SQLException {
+        while (mapping.getJoinablePCSuperclassMapping() != null)
+            mapping = mapping.getJoinablePCSuperclassMapping();
+
+        Version vers = mapping.getVersion();
+        if (!bufferCustomUpdate(vers, sm, store, customs))
+            vers.update(sm, store, rowMgr);
+
+        if (versionUpdateOnly) {
+            // if we are only updating the version column, we need to add
+            // in the primary key select
+            mapping.update(sm, store, rowMgr);
+        } else {
+            // otherwise we need to make sure we update the discriminator too
+            Discriminator dsc = mapping.getDiscriminator();
+            if (!bufferCustomUpdate(dsc, sm, store, customs))
+                dsc.update(sm, store, rowMgr);
+        }
+    }
+
+    /**
+     * @see #bufferCustomInsert
+     */
+    private boolean bufferCustomUpdate(Strategy strat, OpenJPAStateManager sm,
+        JDBCStore store, Collection customs) {
+        Boolean custom = strat.isCustomUpdate(sm, store);
+        if (!Boolean.FALSE.equals(custom))
+            customs.add(new CustomMapping(CustomMapping.UPDATE, sm, strat));
+        return Boolean.TRUE.equals(custom);
+    }
+
+    /**
+     * Executes customized mapping updates.
+     */
+    private static class CustomMapping {
+
+        public static final int INSERT = 0;
+        public static final int UPDATE = 1;
+        public static final int DELETE = 3;
+
+        private final int _action;
+        private final OpenJPAStateManager _sm;
+        private final Strategy _strat;
+
+        public CustomMapping(int action, OpenJPAStateManager sm,
+            Strategy strat) {
+            _action = action;
+            _sm = sm;
+            _strat = strat;
+        }
+
+        public void execute(JDBCStore store)
+            throws SQLException {
+            switch (_action) {
+                case INSERT:
+                    _strat.customInsert(_sm, store);
+                    break;
+                case UPDATE:
+                    _strat.customUpdate(_sm, store);
+                    break;
+                case DELETE:
+                    _strat.customDelete(_sm, store);
+                    break;
+            }
+        }
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ClassTableJDBCSeq.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ClassTableJDBCSeq.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ClassTableJDBCSeq.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ClassTableJDBCSeq.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2006 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.openjpa.jdbc.kernel;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.MappingRepository;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.Table;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.lib.conf.Configurations;
+import org.apache.openjpa.lib.meta.ClassArgParser;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.lib.util.Options;
+import org.apache.openjpa.meta.JavaTypes;
+
+/**
+ * Specialization of the {@link TableJDBCSeq} that maintains a
+ * separate sequence count per-class. Table name defaults to
+ * <code>OPENJPA_SEQUENCES_TABLE</code>.
+ *
+ * @author Abe White
+ */
+public class ClassTableJDBCSeq
+    extends TableJDBCSeq {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (ClassTableJDBCSeq.class);
+
+    private final Map _stats = new HashMap();
+    private boolean _ignore = false;
+    private boolean _aliases = false;
+
+    public ClassTableJDBCSeq() {
+        setTable("OPENJPA_SEQUENCES_TABLE");
+    }
+
+    /**
+     * Whether unmapped classes should be ignored as possible primary
+     * key values in the table. Defaults to false.
+     */
+    public boolean getIgnoreUnmapped() {
+        return _ignore;
+    }
+
+    /**
+     * Whether unmapped classes should be ignored as possible primary
+     * key values in the table. Defaults to false.
+     */
+    public void setIgnoreUnmapped(boolean ignore) {
+        _ignore = ignore;
+    }
+
+    /**
+     * @deprecated Use {@link #setIgnoreUnmapped}. Retained for
+     * backwards-compatibility for auto-configuration.
+     */
+    public void setIgnoreVirtual(boolean ignore) {
+        setIgnoreUnmapped(ignore);
+    }
+
+    /**
+     * Whether to use type alises for primary key values in place of class
+     * names. Defaults to false.
+     */
+    public boolean getUseAliases() {
+        return _aliases;
+    }
+
+    /**
+     * Whether to use type alises for primary key values in place of class
+     * names. Defaults to false.
+     */
+    public void setUseAliases(boolean aliases) {
+        _aliases = aliases;
+    }
+
+    protected Status getStatus(ClassMapping mapping) {
+        if (mapping == null)
+            return null;
+        String key = getKey(mapping, false);
+        Status stat = (Status) _stats.get(key);
+        if (stat == null) {
+            stat = new Status();
+            _stats.put(key, stat);
+        }
+        return stat;
+    }
+
+    protected Column addPrimaryKeyColumn(Table table) {
+        DBDictionary dict = getConfiguration().getDBDictionaryInstance();
+        Column pkColumn = table.addColumn(dict.getValidColumnName
+            (getPrimaryKeyColumn(), table));
+        pkColumn.setType(dict.getPreferredType(Types.VARCHAR));
+        pkColumn.setJavaType(JavaTypes.STRING);
+        pkColumn.setSize(dict.characterColumnSize);
+        return pkColumn;
+    }
+
+    protected Object getPrimaryKey(ClassMapping mapping) {
+        if (mapping == null)
+            return null;
+        return getKey(mapping, true);
+    }
+
+    private String getKey(ClassMapping mapping, boolean db) {
+        if (_ignore) {
+            while (mapping.getMappedPCSuperclassMapping() != null)
+                mapping = mapping.getMappedPCSuperclassMapping();
+        } else {
+            while (mapping.getPCSuperclass() != null)
+                mapping = mapping.getPCSuperclassMapping();
+        }
+        if (_aliases)
+            return mapping.getTypeAlias();
+        return mapping.getDescribedType().getName();
+    }
+
+    /////////
+    // Main
+    /////////
+
+    /**
+     * Usage: java org.apache.openjpa.jdbc.kernel.ClassTableJDBCSeq [option]*
+     * -action/-a &lt;add | drop | get | set&gt;
+     * [class name | .java file | .class file | .jdo file] [value]
+     *  Where the following options are recognized.
+     * <ul>
+     * <li><i>-properties/-p &lt;properties file or resource&gt;</i>: The
+     * path or resource name of a OpenJPA properties file containing
+     * information such as connection data as
+     * outlined in {@link JDBCConfiguration}. Optional.</li>
+     * <li><i>-&lt;property name&gt; &lt;property value&gt;</i>: All bean
+     * properties of the OpenJPA {@link JDBCConfiguration} can be set by
+     * using their	names and supplying a value.</li>
+     * </ul>
+     *  The various actions are as follows.
+     * <ul>
+     * <li><i>add</i>: Create the sequence table.</li>
+     * <li><i>drop</i>: Drop the sequence table.</li>
+     * <li><i>get</i>: Print the current sequence value for the given
+     * class.</li>
+     * <li><i>set</i>: Set the sequence value for the given class.</li>
+     * </ul>
+     */
+    public static void main(String[] args)
+        throws Exception {
+        Options opts = new Options();
+        args = opts.setFromCmdLine(args);
+        JDBCConfiguration conf = new JDBCConfigurationImpl();
+        try {
+            if (!run(conf, args, opts))
+                System.out.println(_loc.get("clstable-seq-usage"));
+        } finally {
+            conf.close();
+        }
+    }
+
+    /**
+     * Run the tool. Returns false if invalid options were given.
+     */
+    public static boolean run(JDBCConfiguration conf, String[] args,
+        Options opts)
+        throws Exception {
+        if (opts.containsKey("help") || opts.containsKey("-help"))
+            return false;
+
+        String action = opts.removeProperty("action", "a", null);
+        Configurations.populateConfiguration(conf, opts);
+        return run(conf, args, action, null, null);
+    }
+
+    /**
+     * Run the tool. Return false if an invalid option was given.
+     */
+    public static boolean run(JDBCConfiguration conf, String[] args,
+        String action, MappingRepository repos, ClassLoader loader)
+        throws Exception {
+        ClassTableJDBCSeq seq = new ClassTableJDBCSeq();
+        String props = Configurations.getProperties(conf.getSequence());
+        Configurations.configureInstance(seq, conf, props);
+
+        if (ACTION_DROP.equals(action)) {
+            if (args.length != 0)
+                return false;
+            seq.dropTable();
+        } else if (ACTION_ADD.equals(action)) {
+            if (args.length != 0)
+                return false;
+            seq.refreshTable();
+        } else if (ACTION_GET.equals(action) || ACTION_SET.equals(action)) {
+            if (args.length == 0)
+                return false;
+
+            if (loader == null)
+                loader = conf.getClassResolverInstance().
+                    getClassLoader(ClassTableJDBCSeq.class, null);
+
+            ClassArgParser cap = conf.getMetaDataRepository().
+                getMetaDataFactory().newClassArgParser();
+            cap.setClassLoader(loader);
+            Class cls = cap.parseTypes(args[0])[0];
+
+            if (repos == null)
+                repos = conf.getMappingRepository();
+            ClassMapping mapping = repos.getMapping(cls, null, true);
+
+            Connection conn = conf.getDataSource2(null).getConnection();
+            try {
+                long cur = seq.getSequence(mapping, conn);
+                if (ACTION_GET.equals(action))
+                    System.out.println(mapping + ": " + cur);
+                else {
+                    long set;
+                    if (args.length > 1)
+                        set = Long.parseLong(args[1]);
+                    else
+                        set = cur + seq.getAllocate();
+                    if (set < cur)
+                        set = cur;
+                    else {
+                        Status stat = seq.getStatus(mapping);
+                        seq.setSequence(null, stat, (int) (set - cur), true,
+                            conn);
+                        set = stat.seq;
+                    }
+                    System.err.println(mapping + ": " + set);
+                }
+            }
+            catch (NumberFormatException nfe) {
+                return false;
+            } finally {
+                try {
+                    conn.close();
+                } catch (SQLException se) {
+                }
+            }
+        } else
+            return false;
+        return true;
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ClassTableJDBCSeq.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ConnectionInfo.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ConnectionInfo.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ConnectionInfo.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ConnectionInfo.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2006 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.openjpa.jdbc.kernel;
+
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+
+/**
+ * Struct to hold data about the current connection state.
+ *
+ * @author Abe White
+ */
+public class ConnectionInfo {
+
+    public Result result = null;
+    public OpenJPAStateManager sm = null;
+    public ClassMapping mapping = null;
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ConnectionInfo.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2006 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.openjpa.jdbc.kernel;
+
+import java.util.Collection;
+
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.kernel.DelegatingFetchConfiguration;
+import org.apache.openjpa.util.RuntimeExceptionTranslator;
+
+///////////////////////////////////////////////////////////////
+// NOTE: when adding a public API method, be sure to add it to 
+// JDO and JPA facades!
+///////////////////////////////////////////////////////////////
+
+/**
+ * Delegating fetch configuration that can also perform exception
+ * transation for use in facades.
+ *
+ * @author Abe White
+ * @nojavadoc
+ * @since 4.0
+ */
+public class DelegatingJDBCFetchConfiguration
+    extends DelegatingFetchConfiguration
+    implements JDBCFetchConfiguration {
+
+    /**
+     * Constructor; supply delegate.
+     */
+    public DelegatingJDBCFetchConfiguration(JDBCFetchConfiguration delegate) {
+        super(delegate);
+    }
+
+    /**
+     * Constructor; supply delegate and exception translator.
+     */
+    public DelegatingJDBCFetchConfiguration(JDBCFetchConfiguration delegate,
+        RuntimeExceptionTranslator trans) {
+        super(delegate, trans);
+    }
+
+    /**
+     * Return the JDBC delegate.
+     */
+    public JDBCFetchConfiguration getJDBCDelegate() {
+        return (JDBCFetchConfiguration) getDelegate();
+    }
+
+    public int getEagerFetchMode() {
+        try {
+            return getJDBCDelegate().getEagerFetchMode();
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public JDBCFetchConfiguration setEagerFetchMode(int mode) {
+        try {
+            getJDBCDelegate().setEagerFetchMode(mode);
+            return this;
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public int getSubclassFetchMode() {
+        try {
+            return getJDBCDelegate().getSubclassFetchMode();
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public int getSubclassFetchMode(ClassMapping cls) {
+        try {
+            return getJDBCDelegate().getSubclassFetchMode(cls);
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public JDBCFetchConfiguration setSubclassFetchMode(int mode) {
+        try {
+            getJDBCDelegate().setSubclassFetchMode(mode);
+            return this;
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public int getResultSetType() {
+        try {
+            return getJDBCDelegate().getResultSetType();
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public JDBCFetchConfiguration setResultSetType(int type) {
+        try {
+            getJDBCDelegate().setResultSetType(type);
+            return this;
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public int getFetchDirection() {
+        try {
+            return getJDBCDelegate().getFetchDirection();
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public JDBCFetchConfiguration setFetchDirection(int direction) {
+        try {
+            getJDBCDelegate().setFetchDirection(direction);
+            return this;
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public int getLRSSize() {
+        try {
+            return getJDBCDelegate().getLRSSize();
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public JDBCFetchConfiguration setLRSSize(int lrsSize) {
+        try {
+            getJDBCDelegate().setLRSSize(lrsSize);
+            return this;
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public int getJoinSyntax() {
+        try {
+            return getJDBCDelegate().getJoinSyntax();
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public JDBCFetchConfiguration setJoinSyntax(int syntax) {
+        try {
+            getJDBCDelegate().setJoinSyntax(syntax);
+            return this;
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public String[] getJoins() {
+        try {
+            return getJDBCDelegate().getJoins();
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public boolean hasJoin(String field) {
+        try {
+            return getJDBCDelegate().hasJoin(field);
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public JDBCFetchConfiguration addJoin(String field) {
+        try {
+            getJDBCDelegate().addJoin(field);
+            return this;
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public JDBCFetchConfiguration addJoins(Collection fields) {
+        try {
+            getJDBCDelegate().addJoins(fields);
+            return this;
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public JDBCFetchConfiguration removeJoin(String field) {
+        try {
+            getJDBCDelegate().removeJoin(field);
+            return this;
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public JDBCFetchConfiguration removeJoins(Collection fields) {
+        try {
+            getJDBCDelegate().removeJoins(fields);
+            return this;
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+
+    public JDBCFetchConfiguration clearJoins() {
+        try {
+            getJDBCDelegate().clearJoins();
+            return this;
+        } catch (RuntimeException re) {
+            throw translate(re);
+        }
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/EagerFetchModes.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/EagerFetchModes.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/EagerFetchModes.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/EagerFetchModes.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2006 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.openjpa.jdbc.kernel;
+
+/**
+ * Eager fetch mode constants.
+ *
+ * @author Abe White
+ */
+public interface EagerFetchModes {
+
+    /**
+     * Constant indicating not to try to load subclass data and related
+     * objects when querying for an object.
+     */
+    public static final int EAGER_NONE = 0;
+
+    /**
+     * Constant indicating to load relations and subclass data if possible
+     * without separate queries.
+     */
+    public static final int EAGER_JOIN = 1;
+
+    /**
+     * Constant indicating to load relations and subclass data if possible
+     * using either joins or parallel queries.
+     */
+    public static final int EAGER_PARALLEL = 2;
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/EagerFetchModes.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/GenericResultObjectProvider.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/GenericResultObjectProvider.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/GenericResultObjectProvider.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/GenericResultObjectProvider.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2006 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.openjpa.jdbc.kernel;
+
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.SQLExceptions;
+import org.apache.openjpa.kernel.StoreContext;
+import org.apache.openjpa.lib.rop.ResultObjectProvider;
+import org.apache.openjpa.util.StoreException;
+import org.apache.openjpa.util.UnsupportedException;
+
+/**
+ * Object provider implementation wrapped around a generic {@link Result}.
+ *
+ * @author Abe White
+ */
+public class GenericResultObjectProvider
+    implements ResultObjectProvider {
+
+    private final ClassMapping _mapping;
+    private final JDBCStore _store;
+    private final JDBCFetchConfiguration _fetch;
+    private final Result _res;
+
+    /**
+     * Constructor.
+     *
+     * @param pcClass the base class of the result objects
+     * @param store the store manager to delegate loading to
+     * @param fetch the fetch configuration, or null for default
+     * @param res the result containing the data
+     */
+    public GenericResultObjectProvider(Class pcClass,
+        JDBCStore store, JDBCFetchConfiguration fetch, Result res) {
+        this(store.getConfiguration().getMappingRepository().getMapping
+            (pcClass, store.getContext().getClassLoader(), true),
+            store, fetch, res);
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param mapping the mapping for the base class of the result objects
+     * @param store the store manager to delegate loading to
+     * @param fetch the fetch configuration, or null for default
+     * @param res the result containing the data
+     */
+    public GenericResultObjectProvider(ClassMapping mapping,
+        JDBCStore store, JDBCFetchConfiguration fetch, Result res) {
+        _mapping = mapping;
+        _store = store;
+        if (fetch == null)
+            _fetch = store.getFetchConfiguration();
+        else
+            _fetch = fetch;
+        _res = res;
+    }
+
+    public boolean supportsRandomAccess() {
+        try {
+            return _res.supportsRandomAccess();
+        } catch (Throwable t) {
+            return false;
+        }
+    }
+
+    public void open() {
+    }
+
+    public Object getResultObject()
+        throws SQLException {
+        // rather than use the standard result.load(), we go direct to
+        // the store manager so we can tell it not to load anything additional
+        return ((JDBCStoreManager) _store).load(_mapping,
+            (JDBCFetchState) _fetch.newFetchState(), StoreContext.EXCLUDE_ALL,
+            _res);
+    }
+
+    public boolean next()
+        throws SQLException {
+        return _res.next();
+    }
+
+    public boolean absolute(int pos)
+        throws SQLException {
+        return _res.absolute(pos);
+    }
+
+    public int size()
+        throws SQLException {
+        if (_fetch.getLRSSize() == LRSSizes.SIZE_UNKNOWN
+            || !supportsRandomAccess())
+            return Integer.MAX_VALUE;
+        return _res.size();
+    }
+
+    public void reset() {
+        throw new UnsupportedException();
+    }
+
+    public void close() {
+        _res.close();
+    }
+
+    public void handleCheckedException(Exception e) {
+        if (e instanceof SQLException)
+            throw SQLExceptions.getStore((SQLException) e,
+                _store.getDBDictionary());
+        throw new StoreException(e);
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/GenericResultObjectProvider.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/InstanceResultObjectProvider.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/InstanceResultObjectProvider.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/InstanceResultObjectProvider.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/InstanceResultObjectProvider.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2006 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.openjpa.jdbc.kernel;
+
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.jdbc.sql.SelectExecutor;
+
+/**
+ * Object provider implementation wrapped around a {@link Select}.
+ *
+ * @author Abe White
+ * @nojavadoc
+ */
+public class InstanceResultObjectProvider
+    extends SelectResultObjectProvider {
+
+    private final ClassMapping _mapping;
+
+    /**
+     * Constructor.
+     *
+     * @param sel the select to execute
+     * @param mapping the mapping for the base class of the result objects
+     * @param store the store to delegate loading to
+     * @param fetch the fetch configuration, or null for default
+     */
+    public InstanceResultObjectProvider(SelectExecutor sel,
+        ClassMapping mapping, JDBCStore store, JDBCFetchState fetchState) {
+        super(sel, store, fetchState);
+        _mapping = mapping;
+    }
+
+    public Object getResultObject()
+        throws SQLException {
+        Result res = getResult();
+        ClassMapping mapping = res.getBaseMapping();
+        if (mapping == null)
+            mapping = _mapping;
+        return res.load(mapping, getStore(), (JDBCFetchState) getFetchState());
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/InstanceResultObjectProvider.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCBrokerFactory.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCBrokerFactory.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCBrokerFactory.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCBrokerFactory.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2006 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.openjpa.jdbc.kernel;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Properties;
+
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
+import org.apache.openjpa.jdbc.meta.MappingTool;
+import org.apache.openjpa.kernel.AbstractBrokerFactory;
+import org.apache.openjpa.kernel.Bootstrap;
+import org.apache.openjpa.kernel.BrokerImpl;
+import org.apache.openjpa.kernel.StoreManager;
+import org.apache.openjpa.lib.conf.ConfigurationProvider;
+import org.apache.openjpa.lib.conf.Configurations;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.util.UserException;
+
+/**
+ * BrokerFactory type for use with the JDBC runtime.
+ *
+ * @author Abe White
+ * @author Marc Prud'hommeaux
+ */
+public class JDBCBrokerFactory
+    extends AbstractBrokerFactory {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (JDBCBrokerFactory.class);
+
+    private boolean _synchronizedMappings = false;
+
+    /**
+     * Factory method for constructing a factory from properties. Invoked from
+     * {@link Bootstrap#newBrokerFactory}.
+     */
+    public static JDBCBrokerFactory newInstance(ConfigurationProvider cp) {
+        JDBCConfigurationImpl conf = new JDBCConfigurationImpl();
+        cp.setInto(conf);
+        return new JDBCBrokerFactory(conf);
+    }
+
+    /**
+     * Factory method for obtaining a possibly-pooled factory from properties.
+     * Invoked from {@link Bootstrap#getBrokerFactory}.
+     */
+    public static JDBCBrokerFactory getInstance(ConfigurationProvider cp) {
+        JDBCBrokerFactory factory = (JDBCBrokerFactory) getPooledFactory
+            (cp.getProperties());
+        if (factory != null)
+            return factory;
+
+        factory = newInstance(cp);
+        factory.pool();
+        return factory;
+    }
+
+    /**
+     * Factory method for constructing a factory from a configuration.
+     */
+    public static synchronized JDBCBrokerFactory getInstance
+        (JDBCConfiguration conf) {
+        JDBCBrokerFactory factory = (JDBCBrokerFactory) getPooledFactory
+            (conf.toProperties(false));
+        if (factory != null)
+            return factory;
+
+        factory = new JDBCBrokerFactory(conf);
+        factory.pool();
+        return factory;
+    }
+
+    /**
+     * Construct the factory with the given option settings; however, the
+     * factory construction methods are recommended.
+     */
+    public JDBCBrokerFactory(JDBCConfiguration conf) {
+        super(conf);
+    }
+
+    public Properties getProperties() {
+        // add platform property
+        Properties props = super.getProperties();
+        String db = "Unknown";
+        try {
+            JDBCConfiguration conf = (JDBCConfiguration) getConfiguration();
+            db = conf.getDBDictionaryInstance().platform;
+        } catch (RuntimeException re) {
+        }
+        props.setProperty("Platform",
+            "OpenJPA JDBC Edition: " + db + " Database");
+
+        return props;
+    }
+
+    protected StoreManager newStoreManager() {
+        return new JDBCStoreManager();
+    }
+
+    protected BrokerImpl newBrokerImpl(String user, String pass) {
+        BrokerImpl broker = super.newBrokerImpl(user, pass);
+
+        lock();
+        try {
+            // synchronize mappings; we wait until now to do this so that
+            // we can use the first broker user/pass for connection if no
+            // global login is given
+            if (!_synchronizedMappings) {
+                _synchronizedMappings = true;
+                synchronizeMappings(broker.getClassLoader());
+            }
+
+            return broker;
+        } finally {
+            unlock();
+        }
+    }
+
+    /**
+     * Synchronize the mappings of the classes listed in the configuration.
+     */
+    private void synchronizeMappings(ClassLoader loader) {
+        JDBCConfiguration conf = (JDBCConfiguration) getConfiguration();
+        String action = conf.getSynchronizeMappings();
+        if (action == null || action.length() == 0)
+            return;
+
+        Collection classes = conf.getMetaDataRepository().
+            loadPersistentTypes(false, loader);
+        if (classes.isEmpty())
+            return;
+
+        String props = Configurations.getProperties(action);
+        action = Configurations.getClassName(action);
+        MappingTool tool = new MappingTool(conf, action, false);
+        Configurations.configureInstance(tool, conf, props,
+            "SynchronizeMappings");
+
+        // initialize the schema
+        Class cls;
+        for (Iterator itr = classes.iterator(); itr.hasNext();) {
+            cls = (Class) itr.next();
+            try {
+                tool.run(cls);
+            } catch (IllegalArgumentException iae) {
+                throw new UserException(_loc.get("bad-synch-mappings",
+                    action, Arrays.asList(MappingTool.ACTIONS)));
+            }
+        }
+        tool.record();
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCBrokerFactory.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2006 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.openjpa.jdbc.kernel;
+
+import java.sql.ResultSet;
+import java.util.Collection;
+
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.sql.JoinSyntaxes;
+import org.apache.openjpa.kernel.FetchConfiguration;
+
+/**
+ * JDBC extensions to OpenJPA's {@link FetchConfiguration}.
+ *
+ * @author Abe White
+ * @since 3.0
+ */
+public interface JDBCFetchConfiguration
+    extends FetchConfiguration, EagerFetchModes, LRSSizes, JoinSyntaxes {
+
+    /**
+     * Return the eager fetch mode. Defaults to the
+     * <code>openjpa.jdbc.EagerFetchMode</code> setting.
+     */
+    public int getEagerFetchMode();
+
+    /**
+     * Set the eager fetch mode. Defaults to the
+     * <code>openjpa.jdbc.EagerFetchMode</code> setting.
+     */
+    public JDBCFetchConfiguration setEagerFetchMode(int mode);
+
+    /**
+     * Return the subclass fetch mode. Defaults to the
+     * <code>openjpa.jdbc.SubclassFetchMode</code> setting.
+     */
+    public int getSubclassFetchMode();
+
+    /**
+     * Return the effective subclass fetch mode for the given type.
+     */
+    public int getSubclassFetchMode(ClassMapping cls);
+
+    /**
+     * Set the subclass fetch mode. Defaults to the
+     * <code>openjpa.jdbc.SubclassFetchMode</code> setting.
+     */
+    public JDBCFetchConfiguration setSubclassFetchMode(int mode);
+
+    /**
+     * The result set type to use as a constant from {@link ResultSet}.
+     * Defaults to the <code>openjpa.jdbc.ResultSetType</code> setting.
+     */
+    public int getResultSetType();
+
+    /**
+     * The result set type to use as a constant from {@link ResultSet}.
+     * Defaults to the <code>openjpa.jdbc.ResultSetType</code> setting.
+     */
+    public JDBCFetchConfiguration setResultSetType(int type);
+
+    /**
+     * The fetch direction to use as a constant from {@link ResultSet}.
+     * Defaults to the <code>openjpa.jdbc.FetchDirection</code> setting.
+     */
+    public int getFetchDirection();
+
+    /**
+     * The fetch direction to use as a constant from {@link ResultSet}.
+     * Defaults to the <code>openjpa.jdbc.FetchDirection</code> setting.
+     */
+    public JDBCFetchConfiguration setFetchDirection(int direction);
+
+    /**
+     * The large result set size mode to use.
+     * Defaults to the <code>openjpa.jdbc.LRSSize</code> setting.
+     */
+    public int getLRSSize();
+
+    /**
+     * The large result set size mode to use.
+     * Defaults to the <code>openjpa.jdbc.LRSSize</code> setting.
+     */
+    public JDBCFetchConfiguration setLRSSize(int lrsSize);
+
+    /**
+     * The join syntax to use.
+     */
+    public int getJoinSyntax();
+
+    /**
+     * The join syntax to use.
+     */
+    public JDBCFetchConfiguration setJoinSyntax(int syntax);
+
+    /**
+     * Returns the names of the joins that this component will use
+     * when loading objects. Defaults to the empty set.
+     *
+     * @since 4.0.0
+     */
+    public String[] getJoins();
+
+    /**
+     * Return true if the given fully-qualified join has been added.
+     *
+     * @since 4.0.0
+     */
+    public boolean hasJoin(String field);
+
+    /**
+     * Adds <code>field</code> to the set of fully-qualified field names to
+     * eagerly join when loading objects. Each class can have at most
+     * one to-many eagerly joined fields.
+     *
+     * @since 4.0.0
+     */
+    public JDBCFetchConfiguration addJoin(String field);
+
+    /**
+     * Adds <code>fields</code> to the set of fully-qualified field names to
+     * eagerly join when loading objects. Each class can have at most
+     * one to-many eagerly joined fields.
+     *
+     * @since 4.0.0
+     */
+    public JDBCFetchConfiguration addJoins(Collection fields);
+
+    /**
+     * Removes <code>field</code> to the set of fully-qualified field names to
+     * eagerly join when loading objects.
+     *
+     * @since 4.0.0
+     */
+    public JDBCFetchConfiguration removeJoin(String field);
+
+    /**
+     * Removes <code>fields</code> from the set of fully-qualified
+     * field names to eagerly join when loading objects.
+     *
+     * @since 4.0.0
+     */
+    public JDBCFetchConfiguration removeJoins(Collection fields);
+
+    /**
+     * Clears the set of field names to join when loading data.
+     *
+     * @since 4.0.0
+     */
+    public JDBCFetchConfiguration clearJoins();
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2006 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.openjpa.jdbc.kernel;
+
+import java.sql.ResultSet;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.openjpa.conf.OpenJPAConfiguration;
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.kernel.FetchConfiguration;
+import org.apache.openjpa.kernel.FetchConfigurationImpl;
+import org.apache.openjpa.kernel.FetchState;
+import org.apache.openjpa.kernel.StoreContext;
+import org.apache.openjpa.lib.rop.EagerResultList;
+import org.apache.openjpa.lib.rop.ListResultObjectProvider;
+import org.apache.openjpa.lib.rop.ResultList;
+import org.apache.openjpa.lib.rop.ResultObjectProvider;
+import org.apache.openjpa.lib.rop.SimpleResultList;
+import org.apache.openjpa.lib.rop.SoftRandomAccessResultList;
+import org.apache.openjpa.lib.rop.WindowResultList;
+import org.apache.openjpa.lib.util.Localizer;
+
+/**
+ * JDBC extensions to OpenJPA's {@link FetchConfiguration}.
+ *
+ * @author Abe White
+ * @nojavadoc
+ */
+public class JDBCFetchConfigurationImpl
+    extends FetchConfigurationImpl
+    implements JDBCFetchConfiguration {
+
+    private static final String[] EMPTY_STRINGS = new String[0];
+
+    private static final Localizer _loc = Localizer.forPackage
+        (JDBCFetchConfigurationImpl.class);
+
+    private int _eagerMode = 0;
+    private int _subclassMode = 0;
+    private int _type = 0;
+    private int _direction = 0;
+    private int _size = 0;
+    private int _syntax = 0;
+
+    private Set _joins = null;
+
+    public void setContext(StoreContext ctx) {
+        super.setContext(ctx);
+        JDBCConfiguration conf = getJDBCConfiguration();
+        if (conf == null)
+            return;
+
+        setEagerFetchMode(conf.getEagerFetchModeConstant());
+        setSubclassFetchMode(conf.getSubclassFetchModeConstant());
+        setResultSetType(conf.getResultSetTypeConstant());
+        setFetchDirection(conf.getFetchDirectionConstant());
+        setLRSSize(conf.getLRSSizeConstant());
+        setJoinSyntax(conf.getDBDictionaryInstance().joinSyntax);
+    }
+
+    protected FetchConfigurationImpl newInstance() {
+        JDBCFetchConfigurationImpl fetch = new JDBCFetchConfigurationImpl();
+        return fetch;
+    }
+
+    public void copy(FetchConfiguration fetch) {
+        super.copy(fetch);
+        JDBCFetchConfiguration jf = (JDBCFetchConfiguration) fetch;
+        setEagerFetchMode(jf.getEagerFetchMode());
+        setSubclassFetchMode(jf.getSubclassFetchMode());
+        setResultSetType(jf.getResultSetType());
+        setFetchDirection(jf.getFetchDirection());
+        setLRSSize(jf.getLRSSize());
+        setJoinSyntax(jf.getJoinSyntax());
+        addJoins(Arrays.asList(jf.getJoins()));
+    }
+
+    public int getEagerFetchMode() {
+        return _eagerMode;
+    }
+
+    public JDBCFetchConfiguration setEagerFetchMode(int mode) {
+        if (mode == DEFAULT) {
+            JDBCConfiguration conf = getJDBCConfiguration();
+            if (conf != null)
+                mode = conf.getEagerFetchModeConstant();
+        }
+        if (mode != DEFAULT)
+            _eagerMode = mode;
+        return this;
+    }
+
+    public int getSubclassFetchMode() {
+        return _subclassMode;
+    }
+
+    public int getSubclassFetchMode(ClassMapping cls) {
+        if (cls == null)
+            return _subclassMode;
+        int mode = cls.getSubclassFetchMode();
+        if (mode == DEFAULT)
+            return _subclassMode;
+        return Math.min(mode, _subclassMode);
+    }
+
+    public JDBCFetchConfiguration setSubclassFetchMode(int mode) {
+        if (mode == DEFAULT) {
+            JDBCConfiguration conf = getJDBCConfiguration();
+            if (conf != null)
+                mode = conf.getSubclassFetchModeConstant();
+        }
+        if (mode != DEFAULT)
+            _subclassMode = mode;
+        return this;
+    }
+
+    public int getResultSetType() {
+        return _type;
+    }
+
+    public JDBCFetchConfiguration setResultSetType(int type) {
+        if (type == DEFAULT) {
+            JDBCConfiguration conf = getJDBCConfiguration();
+            if (conf != null)
+                _type = conf.getResultSetTypeConstant();
+        } else
+            _type = type;
+        return this;
+    }
+
+    public int getFetchDirection() {
+        return _direction;
+    }
+
+    public JDBCFetchConfiguration setFetchDirection(int direction) {
+        if (direction == DEFAULT) {
+            JDBCConfiguration conf = getJDBCConfiguration();
+            if (conf != null)
+                _direction = conf.getFetchDirectionConstant();
+        } else
+            _direction = direction;
+        return this;
+    }
+
+    public int getLRSSize() {
+        return _size;
+    }
+
+    public JDBCFetchConfiguration setLRSSize(int size) {
+        if (size == DEFAULT) {
+            JDBCConfiguration conf = getJDBCConfiguration();
+            if (conf != null)
+                _size = conf.getLRSSizeConstant();
+        } else
+            _size = size;
+        return this;
+    }
+
+    public int getJoinSyntax() {
+        return _syntax;
+    }
+
+    public JDBCFetchConfiguration setJoinSyntax(int syntax) {
+        if (syntax == DEFAULT) {
+            JDBCConfiguration conf = getJDBCConfiguration();
+            if (conf != null)
+                _syntax = conf.getDBDictionaryInstance().joinSyntax;
+        } else
+            _syntax = syntax;
+        return this;
+    }
+
+    public ResultList newResultList(ResultObjectProvider rop) {
+        // if built around a list, just use a simple wrapper
+        if (rop instanceof ListResultObjectProvider)
+            return new SimpleResultList(rop);
+
+        // if built around a paging list, use a window provider with the
+        // same window size
+        if (rop instanceof PagingResultObjectProvider)
+            return new WindowResultList(rop, ((PagingResultObjectProvider)
+                rop).getPageSize());
+
+        // if fetch size < 0 just read in all results immediately
+        if (getFetchBatchSize() < 0)
+            return new EagerResultList(rop);
+
+        // if foward only or forward direction use a forward window
+        if (_type == ResultSet.TYPE_FORWARD_ONLY
+            || _direction == ResultSet.FETCH_FORWARD
+            || !rop.supportsRandomAccess()) {
+            if (getFetchBatchSize() > 0 && getFetchBatchSize() <= 50)
+                return new WindowResultList(rop, getFetchBatchSize());
+            return new WindowResultList(rop, 50);
+        }
+
+        // if skipping around use a caching random access list
+        if (_direction == ResultSet.FETCH_UNKNOWN)
+            return new SoftRandomAccessResultList(rop);
+
+        // scrolling reverse... just use non-caching simple result list
+        return new SimpleResultList(rop);
+    }
+
+    /**
+     * Access JDBC configuration information. May return null if not a
+     * JDBC back-end (possible to get a JDBCFetchConfiguration on non-JDBC
+     * back end in remote client).
+     */
+    private JDBCConfiguration getJDBCConfiguration() {
+        StoreContext ctx = getContext();
+        if (ctx == null)
+            return null;
+
+        OpenJPAConfiguration conf = ctx.getConfiguration();
+        if (!(conf instanceof JDBCConfiguration))
+            return null;
+        return (JDBCConfiguration) conf;
+    }
+
+    public synchronized String[] getJoins() {
+        if (_joins == null || _joins.isEmpty())
+            return EMPTY_STRINGS;
+        return (String[]) _joins.toArray(new String[_joins.size()]);
+    }
+
+    public synchronized boolean hasJoin(String field) {
+        return _joins != null && field != null && _joins.contains(field);
+    }
+
+    public synchronized JDBCFetchConfiguration addJoin(String field) {
+        if (_joins == null)
+            _joins = new HashSet();
+        _joins.add(field);
+        return this;
+    }
+
+    public synchronized JDBCFetchConfiguration addJoins(Collection fields) {
+        if (fields.isEmpty())
+            return this;
+        if (_joins == null)
+            _joins = new HashSet();
+        _joins.addAll(fields);
+        return this;
+    }
+
+    public synchronized JDBCFetchConfiguration removeJoin(String field) {
+        if (_joins != null)
+            _joins.remove(field);
+        return this;
+    }
+
+    public synchronized JDBCFetchConfiguration removeJoins(Collection fields) {
+        if (_joins != null)
+            _joins.removeAll(fields);
+        return this;
+    }
+
+    public synchronized JDBCFetchConfiguration clearJoins() {
+        if (_joins != null)
+            _joins.clear();
+        return this;
+    }
+
+    public FetchState newFetchState() {
+        return new JDBCFetchStateImpl(this);
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchState.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchState.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchState.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchState.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2006 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.openjpa.jdbc.kernel;
+
+import org.apache.openjpa.kernel.FetchState;
+
+/**
+ * Store-specific extension of {@link org.apache.openjpa.kernel.FetchState FetchState}.
+ *
+ * @author <A HREF="mailto:pinaki.poddar@gmail.com>Pinaki Poddar</A>
+ */
+public interface JDBCFetchState
+    extends FetchState {
+
+    /**
+     * Returns store-specific fetch configuration.
+     */
+    public JDBCFetchConfiguration getJDBCFetchConfiguration();
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchState.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchStateImpl.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchStateImpl.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchStateImpl.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchStateImpl.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2006 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.openjpa.jdbc.kernel;
+
+import org.apache.openjpa.kernel.FetchStateImpl;
+
+/**
+ * JDBC-specific implementation of fetch state.
+ *
+ * @author <A HREF="mailto:pinaki.poddar@gmail.com>Pinaki Poddar</A>
+ * @nojavadoc
+ */
+class JDBCFetchStateImpl
+    extends FetchStateImpl
+    implements JDBCFetchState {
+
+    /**
+     * Supply immutable configuration.
+     *
+     * @param fc
+     */
+    JDBCFetchStateImpl(JDBCFetchConfiguration fc) {
+        super(fc);
+    }
+
+    public JDBCFetchConfiguration getJDBCFetchConfiguration() {
+        return (JDBCFetchConfiguration) super.getFetchConfiguration();
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchStateImpl.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCLockManager.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCLockManager.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCLockManager.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCLockManager.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2006 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.openjpa.jdbc.kernel;
+
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.kernel.LockManager;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+
+/**
+ * Extension of the {@link LockManager} interface with methods for
+ * datastore locking during the select and load process. Implementors of
+ * this interface can also take advantage of the fact that in the
+ * {@link LockManager#lock} and {@link LockManager#lockAll} methods, the
+ * given <code>conn</code> parameter, if any, will be an instance of
+ * {@link ConnectionInfo}.
+ *
+ * @author Abe White
+ */
+public interface JDBCLockManager
+    extends LockManager {
+
+    /**
+     * Return whether to issue the given select FOR UPDATE, depending on
+     * the capabilities of the dictionary and the fetch configuration.
+     */
+    public boolean selectForUpdate(Select sel, int lockLevel);
+
+    /**
+     * Notification that the given instance was loaded via a result set
+     * produced by a FOR UPDATE select.
+     */
+    public void loadedForUpdate(OpenJPAStateManager sm);
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCLockManager.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCSeq.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCSeq.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCSeq.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCSeq.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2006 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.openjpa.jdbc.kernel;
+
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.schema.SchemaGroup;
+import org.apache.openjpa.kernel.Seq;
+
+/**
+ * Specialization of the the {@link Seq} interface to provide information
+ * on the schema needed by this sequence. Only sequences that require special
+ * tables that must be created by OpenJPA tools need to implement this
+ * interface.
+ *
+ * @author Abe White
+ */
+public interface JDBCSeq
+    extends Seq {
+
+    /**
+     * Add any tables, etc needed by this factory for the given mapping
+     * to the given schema group, if they do not exist already.
+     */
+    public void addSchema(ClassMapping mapping, SchemaGroup group);
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCSeq.java
------------------------------------------------------------------------------
    svn:executable = *