jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ju...@apache.org
Subject svn commit: r631371 - in /jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle: ./ util/
Date Tue, 26 Feb 2008 20:50:58 GMT
Author: jukka
Date: Tue Feb 26 12:50:53 2008
New Revision: 631371

URL: http://svn.apache.org/viewvc?rev=631371&view=rev
Log:
JCR-1400: Backport JCR-940: add db connection autoConnect for BundleDbPersistenceManager
    - Patch by Alexander Klimetschek (without the JCR-1116 changes)

Added:
    jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionRecoveryManager.java
      - copied, changed from r575734, jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionRecoveryManager.java
Modified:
    jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
    jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java
    jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/DerbyPersistenceManager.java
    jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/H2PersistenceManager.java
    jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/Oracle9PersistenceManager.java
    jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/OraclePersistenceManager.java
    jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/DbNameIndex.java
    jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/NGKDbNameIndex.java

Modified: jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java?rev=631371&r1=631370&r2=631371&view=diff
==============================================================================
--- jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java (original)
+++ jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java Tue Feb 26 12:50:53 2008
@@ -16,39 +16,39 @@
  */
 package org.apache.jackrabbit.core.persistence.bundle;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.jackrabbit.core.fs.FileSystemResource;
-import org.apache.jackrabbit.core.fs.FileSystem;
-import org.apache.jackrabbit.core.state.ItemState;
-import org.apache.jackrabbit.core.state.ChangeLog;
-import org.apache.jackrabbit.core.state.ItemStateException;
-import org.apache.jackrabbit.core.state.NodeReferences;
-import org.apache.jackrabbit.core.state.NoSuchItemStateException;
-import org.apache.jackrabbit.core.state.NodeReferencesId;
-import org.apache.jackrabbit.core.state.PropertyState;
-import org.apache.jackrabbit.core.state.NodeState;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.jcr.PropertyType;
+
+import org.apache.jackrabbit.core.NamespaceRegistryImpl;
 import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.PropertyId;
-import org.apache.jackrabbit.core.NamespaceRegistryImpl;
+import org.apache.jackrabbit.core.fs.FileSystem;
+import org.apache.jackrabbit.core.fs.FileSystemResource;
 import org.apache.jackrabbit.core.nodetype.PropDefId;
-import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.core.persistence.PMContext;
 import org.apache.jackrabbit.core.persistence.PersistenceManager;
-import org.apache.jackrabbit.core.persistence.bundle.util.StringIndex;
-import org.apache.jackrabbit.core.persistence.bundle.util.NamespaceIndex;
-import org.apache.jackrabbit.core.persistence.bundle.util.NodePropBundle;
 import org.apache.jackrabbit.core.persistence.bundle.util.BundleCache;
-import org.apache.jackrabbit.core.persistence.bundle.util.LRUNodeIdCache;
 import org.apache.jackrabbit.core.persistence.bundle.util.HashMapIndex;
+import org.apache.jackrabbit.core.persistence.bundle.util.LRUNodeIdCache;
+import org.apache.jackrabbit.core.persistence.bundle.util.NamespaceIndex;
+import org.apache.jackrabbit.core.persistence.bundle.util.NodePropBundle;
+import org.apache.jackrabbit.core.persistence.bundle.util.StringIndex;
+import org.apache.jackrabbit.core.state.ChangeLog;
+import org.apache.jackrabbit.core.state.ItemState;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.NoSuchItemStateException;
+import org.apache.jackrabbit.core.state.NodeReferences;
+import org.apache.jackrabbit.core.state.NodeReferencesId;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.state.PropertyState;
+import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.name.QName;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import javax.jcr.PropertyType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * The <code>AbstractBundlePersistenceManager</code> acts as base for all

Modified: jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java?rev=631371&r1=631370&r2=631371&view=diff
==============================================================================
--- jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java (original)
+++ jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java Tue Feb 26 12:50:53 2008
@@ -26,6 +26,7 @@
 import org.apache.jackrabbit.core.state.NodeReferences;
 import org.apache.jackrabbit.core.persistence.PMContext;
 import org.apache.jackrabbit.core.persistence.AbstractPersistenceManager;
+import org.apache.jackrabbit.core.persistence.bundle.util.ConnectionRecoveryManager;
 import org.apache.jackrabbit.core.persistence.bundle.util.DbNameIndex;
 import org.apache.jackrabbit.core.persistence.bundle.util.NodePropBundle;
 import org.apache.jackrabbit.core.persistence.bundle.util.BundleBinding;
@@ -54,15 +55,14 @@
 import java.sql.Blob;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
-import java.sql.DriverManager;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
-import java.sql.Driver;
-import java.util.Iterator;
-import java.util.Collection;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
 
 import javax.jcr.RepositoryException;
 
@@ -83,6 +83,7 @@
  * <li>&lt;param name="{@link #setSchema(String) schema}" value=""/>
  * <li>&lt;param name="{@link #setSchemaObjectPrefix(String) schemaObjectPrefix}" value=""/>
  * <li>&lt;param name="{@link #setErrorHandling(String) errorHandling}" value=""/>
+ * <li>&lt;param name="{@link #setBlockOnConnectionLoss(String) blockOnConnectionLoss}" value="false"/>
  * </ul>
  */
 public class BundleDbPersistenceManager extends AbstractBundlePersistenceManager {
@@ -136,21 +137,25 @@
     /** inidicates if uses (filesystem) blob store */
     protected boolean externalBLOBs;
 
+    /** indicates whether to block if the database connection is lost */
+    protected boolean blockOnConnectionLoss = false;
+
+    /**
+     * The class that manages statement execution and recovery from connection loss.
+     */
+    protected ConnectionRecoveryManager connectionManager;
 
-    /** jdbc conection */
-    protected Connection con;
+    // SQL statements for bundle management
+    protected String bundleInsertSQL;
+    protected String bundleUpdateSQL;
+    protected String bundleSelectSQL;
+    protected String bundleDeleteSQL;
 
-    // shared prepared statements for bundle management
-    protected PreparedStatement bundleInsert;
-    protected PreparedStatement bundleUpdate;
-    protected PreparedStatement bundleSelect;
-    protected PreparedStatement bundleDelete;
-
-    // shared prepared statements for NodeReference management
-    protected PreparedStatement nodeReferenceInsert;
-    protected PreparedStatement nodeReferenceUpdate;
-    protected PreparedStatement nodeReferenceSelect;
-    protected PreparedStatement nodeReferenceDelete;
+    // SQL statements for NodeReference management
+    protected String nodeReferenceInsertSQL;
+    protected String nodeReferenceUpdateSQL;
+    protected String nodeReferenceSelectSQL;
+    protected String nodeReferenceDeleteSQL;
 
     /** file system where BLOB data is stored */
     protected CloseableBLOBStore blobStore;
@@ -372,6 +377,14 @@
         return errorHandling.toString();
     }
 
+    public void setBlockOnConnectionLoss(String block) {
+        this.blockOnConnectionLoss = Boolean.valueOf(block).booleanValue();
+    }
+
+    public String getBlockOnConnectionLoss() {
+        return Boolean.toString(blockOnConnectionLoss);
+    }
+
     /**
      * Returns <code>true</code> if the blobs are stored in the DB.
      * @return <code>true</code> if the blobs are stored in the DB.
@@ -405,7 +418,7 @@
                 throw new RepositoryException(msg);
             }
             BufferedReader reader = new BufferedReader(new InputStreamReader(in));
-            Statement stmt = con.createStatement();
+            Statement stmt = connectionManager.getConnection().createStatement();
             try {
                 String sql = reader.readLine();
                 while (sql != null) {
@@ -440,10 +453,11 @@
      * @return <code>true</code> if the tables exist;
      *         <code>false</code> otherwise.
      *
-     * @throws SQLException if an SQL erro occurs.
+     * @throws SQLException if a database error occurs.
+     * @throws RepositoryException if a repository exception occurs.
      */
-    protected boolean checkTablesExist() throws SQLException {
-        DatabaseMetaData metaData = con.getMetaData();
+    protected boolean checkTablesExist() throws SQLException, RepositoryException {
+        DatabaseMetaData metaData = connectionManager.getConnection().getMetaData();
         String tableName = schemaObjectPrefix + "BUNDLE";
         if (metaData.storesLowerCaseIdentifiers()) {
             tableName = tableName.toLowerCase();
@@ -477,37 +491,37 @@
      *
      * Basically wrapps a JDBC transaction around super.store().
      */
-    public synchronized void store(ChangeLog changeLog)
-            throws ItemStateException {
-
-        try {
-            con.setAutoCommit(false);
-            super.store(changeLog);
-        } catch (SQLException e) {
-            String msg = "setting autocommit failed.";
-            log.error(msg, e);
-            throw new ItemStateException(msg, e);
-        } catch (ItemStateException e) {
-            // storing the changes failed, rollback changes
+    public synchronized void store(ChangeLog changeLog) throws ItemStateException {
+        int trials = 2;
+        Throwable lastException  = null;
+        do {
+            trials--;
+            Connection con = null;
             try {
-                con.rollback();
-            } catch (SQLException e1) {
-                String msg = "rollback of change log failed";
-                log.error(msg, e1);
+                con = connectionManager.getConnection();
+                connectionManager.setAutoReconnect(false);
+                con.setAutoCommit(false);
+                super.store(changeLog);
+                con.commit();
+                con.setAutoCommit(true);
+                return;
+            } catch (Throwable th) {
+                lastException = th;
+                try {
+                    if (con != null) {
+                        con.rollback();
+                    }
+                } catch (SQLException e) {
+                    logException("rollback failed", e);
+                }
+                if (th instanceof SQLException || th.getCause() instanceof SQLException) {
+                    connectionManager.close();
+                }
+            } finally {
+                connectionManager.setAutoReconnect(true);
             }
-            // re-throw original exception
-            throw e;
-        }
-
-        // storing the changes succeeded, now commit the changes
-        try {
-            con.commit();
-            con.setAutoCommit(true);
-        } catch (SQLException e) {
-            String msg = "committing change log failed";
-            log.error(msg, e);
-            throw new ItemStateException(msg, e);
-        }
+        } while(blockOnConnectionLoss || trials > 0);
+        throw new ItemStateException(lastException.getMessage());
     }
 
     /**
@@ -521,14 +535,8 @@
 
         this.name = context.getHomeDir().getName();
 
-        // setup jdbc connection
-        // Note: Explicit creation of new instance of the driver is required
-        // in order to re-register the driver in the DriverManager after a
-        // repository shutdown.
-        Driver drv = (Driver) Class.forName(driver).newInstance();
-        log.info("JDBC driver created: {}", drv);
-        con = DriverManager.getConnection(url, user, password);
-        con.setAutoCommit(true);
+        connectionManager = new ConnectionRecoveryManager(blockOnConnectionLoss,
+                getDriver(), getUrl(), getUser(), getPassword());
 
         // make sure schemaObjectPrefix consists of legal name characters only
         prepareSchemaObjectPrefix();
@@ -539,28 +547,8 @@
         // create correct blob store
         blobStore = createBlobStore();
 
-        // prepare statements
-        if (getStorageModel() == SM_BINARY_KEYS) {
-            bundleInsert = con.prepareStatement("insert into " + schemaObjectPrefix + "BUNDLE (BUNDLE_DATA, NODE_ID) values (?, ?)");
-            bundleUpdate = con.prepareStatement("update " + schemaObjectPrefix + "BUNDLE set BUNDLE_DATA = ? where NODE_ID = ?");
-            bundleSelect = con.prepareStatement("select BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE where NODE_ID = ?");
-            bundleDelete = con.prepareStatement("delete from " + schemaObjectPrefix + "BUNDLE where NODE_ID = ?");
-
-            nodeReferenceInsert = con.prepareStatement("insert into " + schemaObjectPrefix + "REFS (REFS_DATA, NODE_ID) values (?, ?)");
-            nodeReferenceUpdate = con.prepareStatement("update " + schemaObjectPrefix + "REFS set REFS_DATA = ? where NODE_ID = ?");
-            nodeReferenceSelect = con.prepareStatement("select REFS_DATA from " + schemaObjectPrefix + "REFS where NODE_ID = ?");
-            nodeReferenceDelete = con.prepareStatement("delete from " + schemaObjectPrefix + "REFS where NODE_ID = ?");
-        } else {
-            bundleInsert = con.prepareStatement("insert into " + schemaObjectPrefix + "BUNDLE (BUNDLE_DATA, NODE_ID_HI, NODE_ID_LO) values (?, ?, ?)");
-            bundleUpdate = con.prepareStatement("update " + schemaObjectPrefix + "BUNDLE set BUNDLE_DATA = ? where NODE_ID_HI = ? and NODE_ID_LO = ?");
-            bundleSelect = con.prepareStatement("select BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE where NODE_ID_HI = ? and NODE_ID_LO = ?");
-            bundleDelete = con.prepareStatement("delete from " + schemaObjectPrefix + "BUNDLE where NODE_ID_HI = ? and NODE_ID_LO = ?");
-
-            nodeReferenceInsert = con.prepareStatement("insert into " + schemaObjectPrefix + "REFS (REFS_DATA, NODE_ID_HI, NODE_ID_LO) values (?, ?, ?)");
-            nodeReferenceUpdate = con.prepareStatement("update " + schemaObjectPrefix + "REFS set REFS_DATA = ? where NODE_ID_HI = ? and NODE_ID_LO = ?");
-            nodeReferenceSelect = con.prepareStatement("select REFS_DATA from " + schemaObjectPrefix + "REFS where NODE_ID_HI = ? and NODE_ID_LO = ?");
-            nodeReferenceDelete = con.prepareStatement("delete from " + schemaObjectPrefix + "REFS where NODE_ID_HI = ? and NODE_ID_LO = ?");
-        }
+        buildSQLStatements();
+
         // load namespaces
         binding = new BundleBinding(errorHandling, blobStore, getNsIndex(), getNameIndex());
         binding.setMinBlobSize(minBlobSize);
@@ -613,7 +601,7 @@
      * @throws SQLException if an SQL error occurs.
      */
     protected DbNameIndex createDbNameIndex() throws SQLException {
-        return new DbNameIndex(con, schemaObjectPrefix);
+        return new DbNameIndex(connectionManager, schemaObjectPrefix);
     }
 
     /**
@@ -667,20 +655,16 @@
         log.info("{}: checking workspace consistency...", name);
 
         Collection modifications = new ArrayList();
-        PreparedStatement stmt = null;
         ResultSet rs = null;
         DataInputStream din = null;
         try {
+            String sql;
             if (getStorageModel() == SM_BINARY_KEYS) {
-                stmt = con.prepareStatement(
-                        "select NODE_ID, BUNDLE_DATA from "
-                        + schemaObjectPrefix + "BUNDLE");
+                sql = "select NODE_ID, BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE";
             } else {
-                stmt = con.prepareStatement(
-                        "select NODE_ID_HI, NODE_ID_LO, BUNDLE_DATA from "
-                        + schemaObjectPrefix + "BUNDLE");
+                sql = "select NODE_ID_HI, NODE_ID_LO, BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE";
             }
-            stmt.execute();
+            Statement stmt = connectionManager.executeStmt(sql, new Object[0]);
             rs = stmt.getResultSet();
             while (rs.next()) {
                 NodeId id;
@@ -751,7 +735,6 @@
         } finally {
             closeStream(din);
             closeResultSet(rs);
-            closeStatement(stmt);
         }
 
         if (consistencyFix && !modifications.isEmpty()) {
@@ -781,7 +764,7 @@
      * @throws Exception if an error occurs
      */
     protected void prepareSchemaObjectPrefix() throws Exception {
-        DatabaseMetaData metaData = con.getMetaData();
+        DatabaseMetaData metaData = connectionManager.getConnection().getMetaData();
         String legalChars = metaData.getExtraNameCharacters();
         legalChars += "ABCDEFGHIJKLMNOPQRSTUVWXZY0123456789_";
 
@@ -811,24 +794,10 @@
         }
 
         try {
-            // close shared prepared statements
-            closeStatement(bundleInsert);
-            closeStatement(bundleUpdate);
-            closeStatement(bundleSelect);
-            closeStatement(bundleDelete);
-
-            closeStatement(nodeReferenceInsert);
-            closeStatement(nodeReferenceUpdate);
-            closeStatement(nodeReferenceSelect);
-            closeStatement(nodeReferenceDelete);
-
             if (nameIndex instanceof DbNameIndex) {
                 ((DbNameIndex) nameIndex).close();
             }
-
-            // close jdbc connection
-            con.close();
-
+            connectionManager.close();
             // close blob store
             blobStore.close();
             blobStore = null;
@@ -859,16 +828,63 @@
     }
 
     /**
+     * Constructs a parameter list for a PreparedStatement
+     * for the given UUID.
+     *
+     * @param uuid the uuid
+     * @return a list of Objects
+     */
+    protected Object[] getKey(UUID uuid) {
+        if (getStorageModel() == SM_BINARY_KEYS) {
+            return new Object[]{uuid.getRawBytes()};
+        } else {
+            return new Object[]{new Long(uuid.getMostSignificantBits()),
+                    new Long(uuid.getLeastSignificantBits())};
+        }
+    }
+
+    /**
+     * Creates a parameter array for an SQL statement that needs
+     * (i) a UUID, and (2) another parameter.
+     *
+     * @param uuid the UUID
+     * @param p the other parameter
+     * @param before whether the other parameter should be before the uuid parameter
+     * @return an Object array that represents the parameters
+     */
+    protected Object[] createParams(UUID uuid, Object p, boolean before) {
+
+        // Create the key
+        List key = new ArrayList();
+        if (getStorageModel() == SM_BINARY_KEYS) {
+            key.add(uuid.getRawBytes());
+        } else {
+            key.add(new Long(uuid.getMostSignificantBits()));
+            key.add(new Long(uuid.getLeastSignificantBits()));
+        }
+
+        // Create the parameters
+        List params = new ArrayList();
+        if (before) {
+            params.add(p);
+            params.addAll(key);
+        } else {
+            params.addAll(key);
+            params.add(p);
+        }
+
+        return params.toArray();
+    }
+
+    /**
      * {@inheritDoc}
      */
     protected synchronized NodePropBundle loadBundle(NodeId id)
             throws ItemStateException {
-        PreparedStatement stmt = bundleSelect;
         ResultSet rs = null;
         InputStream in = null;
         try {
-            setKey(stmt, id.getUUID(), 1);
-            stmt.execute();
+            Statement stmt = connectionManager.executeStmt(bundleSelectSQL, getKey(id.getUUID()));
             rs = stmt.getResultSet();
             if (!rs.next()) {
                 return null;
@@ -893,7 +909,6 @@
         } finally {
             closeStream(in);
             closeResultSet(rs);
-            resetStatement(stmt);
         }
     }
 
@@ -901,13 +916,10 @@
      * {@inheritDoc}
      */
     protected synchronized boolean existsBundle(NodeId id) throws ItemStateException {
-        PreparedStatement stmt = bundleSelect;
         ResultSet rs = null;
         try {
-            setKey(stmt, id.getUUID(), 1);
-            stmt.execute();
+            Statement stmt = connectionManager.executeStmt(bundleSelectSQL, getKey(id.getUUID()));
             rs = stmt.getResultSet();
-
             // a bundle exists, if the result has at least one entry
             return rs.next();
         } catch (Exception e) {
@@ -916,7 +928,6 @@
             throw new ItemStateException(msg, e);
         } finally {
             closeResultSet(rs);
-            resetStatement(stmt);
         }
     }
 
@@ -924,27 +935,19 @@
      * {@inheritDoc}
      */
     protected synchronized void storeBundle(NodePropBundle bundle) throws ItemStateException {
-        PreparedStatement stmt = null;
         try {
             ByteArrayOutputStream out = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
             DataOutputStream dout = new DataOutputStream(out);
             binding.writeBundle(dout, bundle);
             dout.close();
 
-            if (bundle.isNew()) {
-                stmt = bundleInsert;
-            } else {
-                stmt = bundleUpdate;
-            }
-            stmt.setBytes(1, out.toByteArray());
-            setKey(stmt, bundle.getId().getUUID(), 2);
-            stmt.execute();
+            String sql = bundle.isNew() ? bundleInsertSQL : bundleUpdateSQL;
+            Object[] params = createParams(bundle.getId().getUUID(), out.toByteArray(), true);
+            connectionManager.executeStmt(sql, params);
         } catch (Exception e) {
             String msg = "failed to write bundle: " + bundle.getId();
             log.error(msg, e);
             throw new ItemStateException(msg, e);
-        } finally {
-            resetStatement(stmt);
         }
     }
 
@@ -952,10 +955,8 @@
      * {@inheritDoc}
      */
     protected synchronized void destroyBundle(NodePropBundle bundle) throws ItemStateException {
-        PreparedStatement stmt = bundleDelete;
         try {
-            setKey(stmt, bundle.getId().getUUID(), 1);
-            stmt.execute();
+            connectionManager.executeStmt(bundleDeleteSQL, getKey(bundle.getId().getUUID()));
             // also delete all
             bundle.removeAllProperties();
         } catch (Exception e) {
@@ -965,8 +966,6 @@
             String msg = "failed to delete bundle: " + bundle.getId();
             log.error(msg, e);
             throw new ItemStateException(msg, e);
-        } finally {
-            resetStatement(stmt);
         }
     }
 
@@ -979,12 +978,11 @@
             throw new IllegalStateException("not initialized");
         }
 
-        PreparedStatement stmt = nodeReferenceSelect;
         ResultSet rs = null;
         InputStream in = null;
         try {
-            setKey(stmt, targetId.getTargetId().getUUID(), 1);
-            stmt.execute();
+            Statement stmt = connectionManager.executeStmt(
+                    nodeReferenceSelectSQL, getKey(targetId.getTargetId().getUUID()));
             rs = stmt.getResultSet();
             if (!rs.next()) {
                 throw new NoSuchItemStateException(targetId.toString());
@@ -1005,7 +1003,6 @@
         } finally {
             closeStream(in);
             closeResultSet(rs);
-            resetStatement(stmt);
         }
     }
 
@@ -1023,34 +1020,25 @@
             throw new IllegalStateException("not initialized");
         }
 
-        PreparedStatement stmt = null;
-        try {
-            // check if insert or update
-            if (exists(refs.getId())) {
-                stmt = nodeReferenceUpdate;
-            } else {
-                stmt = nodeReferenceInsert;
-            }
+        // check if insert or update
+        boolean update = exists(refs.getId());
+        String sql = (update) ? nodeReferenceUpdateSQL : nodeReferenceInsertSQL;
 
-            ByteArrayOutputStream out = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
+        try {
+            ByteArrayOutputStream out =
+                    new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
             // serialize references
             Serializer.serialize(refs, out);
 
-            // we are synchronized on this instance, therefore we do not
-            // not have to additionally synchronize on the preparedStatement
-
-            stmt.setBytes(1, out.toByteArray());
-            setKey(stmt, refs.getTargetId().getUUID(), 2);
-            stmt.execute();
+            Object[] params = createParams(refs.getTargetId().getUUID(), out.toByteArray(), true);
+            connectionManager.executeStmt(sql, params);
 
             // there's no need to close a ByteArrayOutputStream
             //out.close();
         } catch (Exception e) {
-            String msg = "failed to write property state: " + refs.getTargetId();
+            String msg = "failed to write node references: " + refs.getId();
             log.error(msg, e);
             throw new ItemStateException(msg, e);
-        } finally {
-            resetStatement(stmt);
         }
     }
 
@@ -1062,10 +1050,9 @@
             throw new IllegalStateException("not initialized");
         }
 
-        PreparedStatement stmt = nodeReferenceDelete;
         try {
-            setKey(stmt, refs.getTargetId().getUUID(), 1);
-            stmt.execute();
+            connectionManager.executeStmt(nodeReferenceDeleteSQL,
+                    getKey(refs.getTargetId().getUUID()));
         } catch (Exception e) {
             if (e instanceof NoSuchItemStateException) {
                 throw (NoSuchItemStateException) e;
@@ -1073,8 +1060,6 @@
             String msg = "failed to delete references: " + refs.getTargetId();
             log.error(msg, e);
             throw new ItemStateException(msg, e);
-        } finally {
-            resetStatement(stmt);
         }
     }
 
@@ -1086,22 +1071,21 @@
             throw new IllegalStateException("not initialized");
         }
 
-        PreparedStatement stmt = nodeReferenceSelect;
         ResultSet rs = null;
         try {
-            setKey(stmt, targetId.getTargetId().getUUID(), 1);
-            stmt.execute();
+            Statement stmt = connectionManager.executeStmt(nodeReferenceSelectSQL,
+                    getKey(targetId.getTargetId().getUUID()));
             rs = stmt.getResultSet();
 
-            // a reference exists, if the result has at least one entry
+            // a reference exists if the result has at least one entry
             return rs.next();
         } catch (Exception e) {
-            String msg = "failed to check existence of node references: " + targetId;
+            String msg = "failed to check existence of node references: "
+                + targetId;
             log.error(msg, e);
             throw new ItemStateException(msg, e);
         } finally {
             closeResultSet(rs);
-            resetStatement(stmt);
         }
     }
 
@@ -1188,6 +1172,34 @@
     }
 
     /**
+     * Initializes the SQL strings.
+     */
+    protected void buildSQLStatements() {
+        // prepare statements
+        if (getStorageModel() == SM_BINARY_KEYS) {
+            bundleInsertSQL = "insert into " + schemaObjectPrefix + "BUNDLE (BUNDLE_DATA, NODE_ID) values (?, ?)";
+            bundleUpdateSQL = "update " + schemaObjectPrefix + "BUNDLE set BUNDLE_DATA = ? where NODE_ID = ?";
+            bundleSelectSQL = "select BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE where NODE_ID = ?";
+            bundleDeleteSQL = "delete from " + schemaObjectPrefix + "BUNDLE where NODE_ID = ?";
+
+            nodeReferenceInsertSQL = "insert into " + schemaObjectPrefix + "REFS (REFS_DATA, NODE_ID) values (?, ?)";
+            nodeReferenceUpdateSQL = "update " + schemaObjectPrefix + "REFS set REFS_DATA = ? where NODE_ID = ?";
+            nodeReferenceSelectSQL = "select REFS_DATA from " + schemaObjectPrefix + "REFS where NODE_ID = ?";
+            nodeReferenceDeleteSQL = "delete from " + schemaObjectPrefix + "REFS where NODE_ID = ?";
+        } else {
+            bundleInsertSQL = "insert into " + schemaObjectPrefix + "BUNDLE (BUNDLE_DATA, NODE_ID_HI, NODE_ID_LO) values (?, ?, ?)";
+            bundleUpdateSQL = "update " + schemaObjectPrefix + "BUNDLE set BUNDLE_DATA = ? where NODE_ID_HI = ? and NODE_ID_LO = ?";
+            bundleSelectSQL = "select BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE where NODE_ID_HI = ? and NODE_ID_LO = ?";
+            bundleDeleteSQL = "delete from " + schemaObjectPrefix + "BUNDLE where NODE_ID_HI = ? and NODE_ID_LO = ?";
+
+            nodeReferenceInsertSQL = "insert into " + schemaObjectPrefix + "REFS (REFS_DATA, NODE_ID_HI, NODE_ID_LO) values (?, ?, ?)";
+            nodeReferenceUpdateSQL = "update " + schemaObjectPrefix + "REFS set REFS_DATA = ? where NODE_ID_HI = ? and NODE_ID_LO = ?";
+            nodeReferenceSelectSQL = "select REFS_DATA from " + schemaObjectPrefix + "REFS where NODE_ID_HI = ? and NODE_ID_LO = ?";
+            nodeReferenceDeleteSQL = "delete from " + schemaObjectPrefix + "REFS where NODE_ID_HI = ? and NODE_ID_LO = ?";
+        }
+    }
+
+    /**
      * Helper interface for closeable stores
      */
     protected static interface CloseableBLOBStore extends BLOBStore {
@@ -1226,28 +1238,18 @@
      */
     protected class DbBlobStore implements CloseableBLOBStore {
 
-        protected PreparedStatement blobInsert;
-        protected PreparedStatement blobUpdate;
-        protected PreparedStatement blobSelect;
-        protected PreparedStatement blobSelectExist;
-        protected PreparedStatement blobDelete;
+        protected String blobInsertSQL;
+        protected String blobUpdateSQL;
+        protected String blobSelectSQL;
+        protected String blobSelectExistSQL;
+        protected String blobDeleteSQL;
 
         public DbBlobStore() throws SQLException {
-            blobInsert =
-                    con.prepareStatement("insert into "
-                    + schemaObjectPrefix + "BINVAL (BINVAL_DATA, BINVAL_ID) values (?, ?)");
-            blobUpdate =
-                    con.prepareStatement("update "
-                    + schemaObjectPrefix + "BINVAL set BINVAL_DATA = ? where BINVAL_ID = ?");
-            blobSelect =
-                    con.prepareStatement("select BINVAL_DATA from "
-                    + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?");
-            blobSelectExist =
-                    con.prepareStatement("select 1 from "
-                    + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?");
-            blobDelete =
-                    con.prepareStatement("delete from "
-                    + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?");
+            blobInsertSQL = "insert into " + schemaObjectPrefix + "BINVAL (BINVAL_DATA, BINVAL_ID) values (?, ?)";
+            blobUpdateSQL = "update " + schemaObjectPrefix + "BINVAL set BINVAL_DATA = ? where BINVAL_ID = ?";
+            blobSelectSQL = "select BINVAL_DATA from " + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?";
+            blobSelectExistSQL = "select 1 from " + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?";
+            blobDeleteSQL = "delete from " + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?";
         }
 
         /**
@@ -1269,39 +1271,31 @@
          * {@inheritDoc}
          */
         public InputStream get(String blobId) throws Exception {
-            PreparedStatement stmt = blobSelect;
-            synchronized (stmt) {
-                try {
-                    stmt.setString(1, blobId);
-                    stmt.execute();
-                    final ResultSet rs = stmt.getResultSet();
-                    if (!rs.next()) {
-                        closeResultSet(rs);
-                        throw new Exception("no such BLOB: " + blobId);
-                    }
-                    InputStream in = rs.getBinaryStream(1);
-                    if (in == null) {
-                        // some databases treat zero-length values as NULL;
-                        // return empty InputStream in such a case
-                        closeResultSet(rs);
-                        return new ByteArrayInputStream(new byte[0]);
-                    }
+            Statement stmt = connectionManager.executeStmt(blobSelectSQL, new Object[]{blobId});
+            final ResultSet rs = stmt.getResultSet();
+            if (!rs.next()) {
+                closeResultSet(rs);
+                throw new Exception("no such BLOB: " + blobId);
+            }
+            InputStream in = rs.getBinaryStream(1);
+            if (in == null) {
+                // some databases treat zero-length values as NULL;
+                // return empty InputStream in such a case
+                closeResultSet(rs);
+                return new ByteArrayInputStream(new byte[0]);
+            }
 
-                    /**
-                     * return an InputStream wrapper in order to
-                     * close the ResultSet when the stream is closed
-                     */
-                    return new FilterInputStream(in) {
-                        public void close() throws IOException {
-                            in.close();
-                            // now it's safe to close ResultSet
-                            closeResultSet(rs);
-                        }
-                    };
-                } finally {
-                    resetStatement(stmt);
+            /**
+             * return an InputStream wrapper in order to
+             * close the ResultSet when the stream is closed
+             */
+            return new FilterInputStream(in) {
+                public void close() throws IOException {
+                    in.close();
+                    // now it's safe to close ResultSet
+                    closeResultSet(rs);
                 }
-            }
+            };
         }
 
         /**
@@ -1309,45 +1303,28 @@
          */
         public synchronized void put(String blobId, InputStream in, long size)
                 throws Exception {
-            PreparedStatement stmt = blobSelectExist;
-            try {
-                stmt.setString(1, blobId);
-                stmt.execute();
-                ResultSet rs = stmt.getResultSet();
-                // a BLOB exists if the result has at least one entry
-                boolean exists = rs.next();
-                resetStatement(stmt);
-                closeResultSet(rs);
+            Statement stmt = connectionManager.executeStmt(blobSelectExistSQL, new Object[]{blobId});
+            ResultSet rs = stmt.getResultSet();
+            // a BLOB exists if the result has at least one entry
+            boolean exists = rs.next();
+            closeResultSet(rs);
 
-                stmt = (exists) ? blobUpdate : blobInsert;
-                stmt.setBinaryStream(1, in, (int) size);
-                stmt.setString(2, blobId);
-                stmt.executeUpdate();
-            } finally {
-                resetStatement(stmt);
-            }
+            String sql = (exists) ? blobUpdateSQL : blobInsertSQL;
+            Object[] params = new Object[]{new ConnectionRecoveryManager.StreamWrapper(in, size), blobId};
+            connectionManager.executeStmt(sql, params);
         }
 
         /**
          * {@inheritDoc}
          */
         public synchronized boolean remove(String blobId) throws Exception {
-            PreparedStatement stmt = blobDelete;
-            try {
-                stmt.setString(1, blobId);
-                return stmt.executeUpdate() == 1;
-            } finally {
-                resetStatement(stmt);
-            }
+            Statement stmt = connectionManager.executeStmt(blobDeleteSQL, new Object[]{blobId});
+            return stmt.getUpdateCount() == 1;
         }
 
         public void close() {
-            closeStatement(blobInsert);
-            closeStatement(blobUpdate);
-            closeStatement(blobSelect);
-            closeStatement(blobSelectExist);
-            closeStatement(blobDelete);
+            // closing the database resources of this blobstore is left to the
+            // owning BundleDbPersistenceManager
         }
     }
-
 }

Modified: jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/DerbyPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/DerbyPersistenceManager.java?rev=631371&r1=631370&r2=631371&view=diff
==============================================================================
--- jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/DerbyPersistenceManager.java (original)
+++ jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/DerbyPersistenceManager.java Tue Feb 26 12:50:53 2008
@@ -19,9 +19,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.jackrabbit.core.persistence.PMContext;
-import org.apache.jackrabbit.core.persistence.db.DatabasePersistenceManager;
 
-import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.SQLException;
 import java.sql.Statement;
@@ -58,7 +56,7 @@
 
     /** name of the embedded driver */
     public static final String DERBY_EMBEDDED_DRIVER = "org.apache.derby.jdbc.EmbeddedDriver";
-    
+
     /** the default logger */
     private static Logger log = LoggerFactory.getLogger(DerbyPersistenceManager.class);
 
@@ -271,7 +269,7 @@
     protected void checkSchema() throws SQLException, RepositoryException {
         // set properties
         if (DERBY_EMBEDDED_DRIVER.equals(getDriver())) {
-            Statement stmt = con.createStatement();
+            Statement stmt = connectionManager.getConnection().createStatement();
             try {
                 stmt.execute("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY " +
                         "('derby.storage.initialPages', '" + derbyStorageInitialPages + "')");
@@ -317,7 +315,7 @@
         }
 
         // prepare connection url for issuing shutdown command
-        String url = con.getMetaData().getURL();
+        String url = connectionManager.getConnection().getMetaData().getURL();
         int pos = url.lastIndexOf(';');
         if (pos != -1) {
             // strip any attributes from connection url
@@ -329,7 +327,7 @@
         // otherwise Derby would mysteriously complain about some pending uncommitted
         // changes which can't possibly be true.
         // @todo further investigate
-        con.setAutoCommit(true);
+        connectionManager.getConnection().setAutoCommit(true);
 
         // now it's safe to shutdown the embedded Derby database
         try {
@@ -342,4 +340,4 @@
         super.close();
     }
 
-}
\ No newline at end of file
+}

Modified: jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/H2PersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/H2PersistenceManager.java?rev=631371&r1=631370&r2=631371&view=diff
==============================================================================
--- jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/H2PersistenceManager.java (original)
+++ jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/H2PersistenceManager.java Tue Feb 26 12:50:53 2008
@@ -17,7 +17,6 @@
 package org.apache.jackrabbit.core.persistence.bundle;
 
 import org.apache.jackrabbit.core.persistence.PMContext;
-import org.apache.jackrabbit.core.persistence.PersistenceManager;
 
 import java.sql.Statement;
 import java.sql.SQLException;
@@ -103,7 +102,7 @@
      * {@inheritDoc}
      */
     protected void checkSchema() throws SQLException, RepositoryException {
-        Statement stmt = con.createStatement();
+        Statement stmt = connectionManager.getConnection().createStatement();
         try {
             stmt.execute("SET LOCK_TIMEOUT " + lockTimeout);
         } finally {
@@ -121,7 +120,7 @@
         }
         if (getUrl().startsWith("jdbc:h2:file:")) {
             // have to explicitly shutdown in-proc h2
-            Statement stmt = con.createStatement();
+            Statement stmt = connectionManager.getConnection().createStatement();
             stmt.execute("shutdown");
             stmt.close();
         }
@@ -129,4 +128,4 @@
         super.close();
     }
 
-}
\ No newline at end of file
+}

Modified: jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/Oracle9PersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/Oracle9PersistenceManager.java?rev=631371&r1=631370&r2=631371&view=diff
==============================================================================
--- jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/Oracle9PersistenceManager.java (original)
+++ jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/Oracle9PersistenceManager.java Tue Feb 26 12:50:53 2008
@@ -33,9 +33,9 @@
 import java.lang.reflect.Method;
 import java.sql.Blob;
 import java.sql.Connection;
-import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.Statement;
 
 /**
  * <code>OracleLegacyPersistenceManager</code> provides support for Oracle jdbc
@@ -68,8 +68,8 @@
     private static Logger log = LoggerFactory.getLogger(Oracle9PersistenceManager.class);
 
     private Class blobClass;
-    private Integer DURATION_SESSION_CONSTANT;
-    private Integer MODE_READWRITE_CONSTANT;
+    private Integer duractionSessionConstant;
+    private Integer modeReadWriteConstant;
 
     public Oracle9PersistenceManager() {
     }
@@ -92,10 +92,10 @@
 
         // use the Connection object for using the exact same
         // class loader that the Oracle driver was loaded with
-        blobClass = con.getClass().getClassLoader().loadClass("oracle.sql.BLOB");
-        DURATION_SESSION_CONSTANT =
+        blobClass = connectionManager.getConnection().getClass().getClassLoader().loadClass("oracle.sql.BLOB");
+        duractionSessionConstant =
                 new Integer(blobClass.getField("DURATION_SESSION").getInt(null));
-        MODE_READWRITE_CONSTANT =
+        modeReadWriteConstant =
                 new Integer(blobClass.getField("MODE_READWRITE").getInt(null));
     }
 
@@ -111,7 +111,6 @@
      */
     protected synchronized void storeBundle(NodePropBundle bundle)
             throws ItemStateException {
-        PreparedStatement stmt = null;
         Blob blob = null;
         try {
             ByteArrayOutputStream out = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
@@ -119,21 +118,15 @@
             binding.writeBundle(dout, bundle);
             dout.close();
 
-            if (bundle.isNew()) {
-                stmt = bundleInsert;
-            } else {
-                stmt = bundleUpdate;
-            }
+            String sql = bundle.isNew() ? bundleInsertSQL : bundleUpdateSQL;
             blob = createTemporaryBlob(new ByteArrayInputStream(out.toByteArray()));
-            stmt.setBlob(1, blob);
-            stmt.setBytes(2, bundle.getId().getUUID().getRawBytes());
-            stmt.execute();
+            Object[] params = createParams(bundle.getId().getUUID(), blob, true);
+            connectionManager.executeStmt(sql, params);
         } catch (Exception e) {
             String msg = "failed to write bundle: " + bundle.getId();
             log.error(msg, e);
             throw new ItemStateException(msg, e);
         } finally {
-            resetStatement(stmt);
             if (blob != null) {
                 try {
                     freeTemporaryBlob(blob);
@@ -152,15 +145,11 @@
             throw new IllegalStateException("not initialized");
         }
 
-        PreparedStatement stmt = null;
         Blob blob = null;
         try {
             // check if insert or update
-            if (exists(refs.getId())) {
-                stmt = nodeReferenceUpdate;
-            } else {
-                stmt = nodeReferenceInsert;
-            }
+            boolean update = exists(refs.getId());
+            String sql = (update) ? nodeReferenceUpdateSQL : nodeReferenceInsertSQL;
 
             ByteArrayOutputStream out = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
             // serialize references
@@ -170,9 +159,8 @@
             // not have to additionally synchronize on the preparedStatement
 
             blob = createTemporaryBlob(new ByteArrayInputStream(out.toByteArray()));
-            stmt.setBlob(1, blob);
-            stmt.setBytes(2, refs.getTargetId().getUUID().getRawBytes());
-            stmt.execute();
+            Object[] params = createParams(refs.getTargetId().getUUID(), blob, true);
+            connectionManager.executeStmt(sql, params);
 
             // there's no need to close a ByteArrayOutputStream
             //out.close();
@@ -181,7 +169,6 @@
             log.error(msg, e);
             throw new ItemStateException(msg, e);
         } finally {
-            resetStatement(stmt);
             if (blob != null) {
                 try {
                     freeTemporaryBlob(blob);
@@ -210,9 +197,9 @@
         Method createTemporary = blobClass.getMethod("createTemporary",
                 new Class[]{Connection.class, Boolean.TYPE, Integer.TYPE});
         Object blob = createTemporary.invoke(null,
-                new Object[]{con, Boolean.FALSE, DURATION_SESSION_CONSTANT});
+                new Object[]{connectionManager.getConnection(), Boolean.FALSE, duractionSessionConstant});
         Method open = blobClass.getMethod("open", new Class[]{Integer.TYPE});
-        open.invoke(blob, new Object[]{MODE_READWRITE_CONSTANT});
+        open.invoke(blob, new Object[]{modeReadWriteConstant});
         Method getBinaryOutputStream = blobClass.getMethod("getBinaryOutputStream", new Class[0]);
         OutputStream out = (OutputStream) getBinaryOutputStream.invoke(blob, null);
         try {
@@ -253,29 +240,23 @@
          */
         public synchronized void put(String blobId, InputStream in, long size)
                 throws Exception {
-            PreparedStatement stmt = blobSelectExist;
+
             Blob blob = null;
             try {
-                stmt.setString(1, blobId);
-                stmt.execute();
+                Statement stmt = connectionManager.executeStmt(blobSelectExistSQL, new Object[]{blobId});
                 ResultSet rs = stmt.getResultSet();
                 // a BLOB exists if the result has at least one entry
                 boolean exists = rs.next();
-                resetStatement(stmt);
                 closeResultSet(rs);
 
-                stmt = (exists) ? blobUpdate : blobInsert;
-
+                String sql = (exists) ? blobUpdateSQL : blobInsertSQL;
                 blob = createTemporaryBlob(in);
-                stmt.setBlob(1, blob);
-                stmt.setString(2, blobId);
-                stmt.executeUpdate();
+                connectionManager.executeStmt(sql, new Object[]{blob, blobId});
             } finally {
-                resetStatement(stmt);
                 if (blob != null) {
                     try {
                         freeTemporaryBlob(blob);
-                    } catch (Exception e1) {
+                    } catch (Exception e) {
                     }
                 }
             }

Modified: jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/OraclePersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/OraclePersistenceManager.java?rev=631371&r1=631370&r2=631371&view=diff
==============================================================================
--- jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/OraclePersistenceManager.java (original)
+++ jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/OraclePersistenceManager.java Tue Feb 26 12:50:53 2008
@@ -20,8 +20,8 @@
 import java.sql.SQLException;
 
 import org.apache.jackrabbit.core.persistence.PMContext;
-import org.apache.jackrabbit.core.persistence.bundle.util.NGKDbNameIndex;
 import org.apache.jackrabbit.core.persistence.bundle.util.DbNameIndex;
+import org.apache.jackrabbit.core.persistence.bundle.util.NGKDbNameIndex;
 
 /**
  * Extends the {@link BundleDbPersistenceManager} by Oracle specific code.
@@ -75,9 +75,11 @@
             setSchemaObjectPrefix(context.getHomeDir().getName() + "_");
         }
         super.init(context);
+
 /*
         // check driver version
-        DatabaseMetaData metaData = con.getMetaData();
+        DatabaseMetaData metaData =
+            connectionManager.getConnection().getMetaData();
         if (metaData.getDriverMajorVersion() < 10) {
             // oracle drivers prior to version 10 only support
             // writing BLOBs up to 32k in size...
@@ -86,7 +88,7 @@
                     + " v" + metaData.getDriverVersion());
         }
 */
-    }
+        }
 
     /**
      * Retruns a new instance of a NGKDbNameIndex.
@@ -94,7 +96,7 @@
      * @throws SQLException if an SQL error occurs.
      */
     protected DbNameIndex createDbNameIndex() throws SQLException {
-        return new NGKDbNameIndex(con, schemaObjectPrefix);
+        return new NGKDbNameIndex(connectionManager, schemaObjectPrefix);
     }
 
     /**
@@ -114,7 +116,7 @@
      * @inheritDoc
      */
     protected void prepareSchemaObjectPrefix() throws Exception {
-        DatabaseMetaData metaData = con.getMetaData();
+        DatabaseMetaData metaData = connectionManager.getConnection().getMetaData();
         String legalChars = metaData.getExtraNameCharacters();
         legalChars += "ABCDEFGHIJKLMNOPQRSTUVWXZY0123456789_";
 

Copied: jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionRecoveryManager.java (from r575734, jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionRecoveryManager.java)
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionRecoveryManager.java?p2=jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionRecoveryManager.java&p1=jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionRecoveryManager.java&r1=575734&r2=631371&rev=631371&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionRecoveryManager.java (original)
+++ jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionRecoveryManager.java Tue Feb 26 12:50:53 2008
@@ -18,7 +18,6 @@
 
 import java.io.InputStream;
 import java.sql.Connection;
-import java.sql.DatabaseMetaData;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
@@ -26,6 +25,8 @@
 import java.sql.Statement;
 import java.util.HashMap;
 
+import javax.jcr.RepositoryException;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -124,8 +125,9 @@
      * @param url the url to use for the connection
      * @param user the user to use for the connection
      * @param password the password to use for the connection
+     * @throws RepositoryException if the database driver could not be loaded
      */
-    public ConnectionRecoveryManager(boolean block, String driver, String url, String user, String password) {
+    public ConnectionRecoveryManager(boolean block, String driver, String url, String user, String password) throws RepositoryException {
         this.block = block;
         this.driver = driver;
         this.url = url;
@@ -147,8 +149,9 @@
      *
      * @return the database connection that is managed
      * @throws SQLException on error
+     * @throws RepositoryException if the database driver could not be loaded
      */
-    public synchronized Connection getConnection() throws SQLException {
+    public synchronized Connection getConnection() throws SQLException, RepositoryException {
         if (isClosed) {
             if (autoReconnect) {
                 reestablishConnection();
@@ -172,13 +175,38 @@
     }
 
     /**
+     * Executes the given SQL query. Retries once or blocks (when the
+     * <code>block</code> parameter has been set to true on construction)
+     * if this fails and autoReconnect is enabled.
+     *
+     * @param sql the SQL query to execute
+     * @return the executed ResultSet
+     * @throws SQLException on error
+     * @throws RepositoryException if the database driver could not be loaded
+     */
+    public synchronized ResultSet executeQuery(String sql) throws SQLException, RepositoryException {
+        int trials = 2;
+        SQLException lastException  = null;
+        do {
+            trials--;
+            try {
+                return executeQueryInternal(sql);
+            } catch (SQLException e) {
+                lastException = e;
+            }
+        } while(autoReconnect && (block || trials > 0));
+        throw lastException;
+    }
+
+    /**
      * Executes the given SQL query.
      *
      * @param sql query to execute
      * @return a <code>ResultSet</code> object
      * @throws SQLException if an error occurs
+     * @throws RepositoryException if the database driver could not be loaded
      */
-    public synchronized ResultSet executeQuery(String sql) throws SQLException {
+    private ResultSet executeQueryInternal(String sql) throws SQLException, RepositoryException {
         PreparedStatement stmt = null;
         try {
             stmt = (PreparedStatement) preparedStatements.get(sql);
@@ -203,20 +231,34 @@
      * @param params parameters to set
      * @return the <code>Statement</code> object that had been executed
      * @throws SQLException if an error occurs
+     * @throws RepositoryException if the database driver could not be loaded
      */
-    public synchronized Statement executeStmt(String sql, Object[] params) throws SQLException {
-        try {
-            PreparedStatement stmt = (PreparedStatement) preparedStatements.get(sql);
-            if (stmt == null) {
-                stmt = getConnection().prepareStatement(sql);
-                preparedStatements.put(sql, stmt);
+    public Statement executeStmt(String sql, Object[] params) throws SQLException, RepositoryException {
+    	return executeStmt(sql, params, Statement.NO_GENERATED_KEYS);
+    }
+
+    /**
+     * Executes the given SQL statement with the specified parameters.
+     *
+     * @param sql statement to execute
+     * @param params parameters to set
+     * @param autoGeneratedKeys the constant that tells the driver to make auto generated keys available
+     * @return the <code>Statement</code> object that had been executed
+     * @throws SQLException if an error occurs
+     * @throws RepositoryException if the database driver could not be loaded
+     */
+    public synchronized Statement executeStmt(String sql, Object[] params, int autoGeneratedKeys) throws SQLException, RepositoryException {
+        int trials = 2;
+        SQLException lastException  = null;
+        do {
+            trials--;
+            try {
+                return executeStmtInternal(sql, params, autoGeneratedKeys);
+            } catch (SQLException e) {
+                lastException = e;
             }
-            return executeStmtInternal(params, stmt);
-        } catch (SQLException e) {
-            logException("could not execute statement", e);
-            close();
-            throw e;
-        }
+        } while(autoReconnect && (block || trials > 0));
+        throw lastException;
     }
 
     /**
@@ -227,8 +269,9 @@
      * @param autoGeneratedKeys the constant that tells the driver to make auto generated keys available
      * @return the <code>Statement</code> object that had been executed
      * @throws SQLException if an error occurs
+     * @throws RepositoryException if the database driver could not be loaded
      */
-    public synchronized Statement executeStmt(String sql, Object[] params, int autoGeneratedKeys) throws SQLException {
+    private synchronized Statement executeStmtInternal(String sql, Object[] params, int autoGeneratedKeys) throws SQLException, RepositoryException {
         try {
             PreparedStatement stmt = (PreparedStatement) preparedStatements.get(sql + "_" + autoGeneratedKeys);
             if (stmt == null) {
@@ -267,22 +310,25 @@
      * Creates the database connection.
      *
      * @throws SQLException on error
+     * @throws RepositoryException if the database driver could not be loaded
      */
-    private void setupConnection() throws SQLException {
+    private void setupConnection() throws SQLException, RepositoryException {
         try {
-            Class.forName(driver).newInstance();
-        } catch (Exception e) {
-            throw new SQLException("could not load driver: " + e.getMessage());
+            Class driverClass = Class.forName(driver);
+            // Workaround for Apache Derby:
+            // The JDBC specification recommends the Class.ForName method without the .newInstance() method call, 
+            // but adding the newInstance() guarantees that Derby will be booted on any Java Virtual Machine.
+            driverClass.newInstance();
+        } catch (Throwable e) {
+            throw new RepositoryException("Could not load or initialize the database driver class " + driver, e);
         }
-        connection = DriverManager.getConnection(url, user, password);
-        connection.setAutoCommit(true);
         try {
-            DatabaseMetaData meta = connection.getMetaData();
-            log.info("Database: " + meta.getDatabaseProductName() + " / " + meta.getDatabaseProductVersion());
-            log.info("Driver: " + meta.getDriverName() + " / " + meta.getDriverVersion());
+            connection = DriverManager.getConnection(url, user, password);
         } catch (SQLException e) {
-            log.warn("Can not retrieve database and driver name / version", e);
+            log.warn("Could not connect; driver: " + driver + " url: " + url + " user: " + user + " error: " + e.toString(), e);
+            throw e;
         }
+        connection.setAutoCommit(true);
     }
 
     /**
@@ -309,8 +355,9 @@
      * Re-establishes the database connection.
      *
      * @throws SQLException if reconnecting failed
+     * @throws RepositoryException 
      */
-    private void reestablishConnection() throws SQLException {
+    private void reestablishConnection() throws SQLException, RepositoryException {
 
         long trials = TRIALS;
         SQLException exception = null;

Modified: jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/DbNameIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/DbNameIndex.java?rev=631371&r1=631370&r2=631371&view=diff
==============================================================================
--- jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/DbNameIndex.java (original)
+++ jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/DbNameIndex.java Tue Feb 26 12:50:53 2008
@@ -18,8 +18,6 @@
 
 import java.util.HashMap;
 
-import java.sql.Connection;
-import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
@@ -42,14 +40,19 @@
      */
     static final String CVS_ID = "$URL$ $Rev$ $Date$";
 
-    // name index statements
-    protected PreparedStatement nameSelect;
-    protected PreparedStatement indexSelect;
-    protected PreparedStatement nameInsert;
+    /**
+     * The class that manages statement execution and recovery from connection loss.
+     */
+    protected ConnectionRecoveryManager connectionManager;
 
+    // name index statements
+    protected String nameSelectSQL;
+    protected String indexSelectSQL;
+    protected String nameInsertSQL;
+    
     // caches
     private final HashMap string2Index = new HashMap();
-    private final HashMap index2String= new HashMap();
+    private final HashMap index2String = new HashMap();
 
     /**
      * Creates a new index that is stored in a db.
@@ -57,9 +60,10 @@
      * @param schemaObjectPrefix the prefix for table names
      * @throws SQLException if the statements cannot be prepared.
      */
-    public DbNameIndex(Connection con, String schemaObjectPrefix)
+    public DbNameIndex(ConnectionRecoveryManager conMgr, String schemaObjectPrefix)
             throws SQLException {
-        init(con, schemaObjectPrefix);
+        connectionManager = conMgr;
+        init(schemaObjectPrefix);
     }
 
     /**
@@ -69,20 +73,19 @@
      * @param schemaObjectPrefix the prefix for table names
      * @throws SQLException if the statements cannot be prepared.
      */
-    protected void init(Connection con, String schemaObjectPrefix)
+    protected void init(String schemaObjectPrefix)
             throws SQLException {
-        nameSelect = con.prepareStatement("select NAME from " + schemaObjectPrefix + "NAMES where ID = ?");
-        indexSelect = con.prepareStatement("select ID from " + schemaObjectPrefix + "NAMES where NAME = ?");
-        nameInsert = con.prepareStatement("insert into " + schemaObjectPrefix + "NAMES (NAME) values (?)", Statement.RETURN_GENERATED_KEYS);
+        nameSelectSQL = "select NAME from " + schemaObjectPrefix + "NAMES where ID = ?";
+        indexSelectSQL = "select ID from " + schemaObjectPrefix + "NAMES where NAME = ?";
+        nameInsertSQL = "insert into " + schemaObjectPrefix + "NAMES (NAME) values (?)";
     }
 
     /**
      * Closes this index and releases it's resources.
      */
     public void close() {
-        closeStatement(nameSelect);
-        closeStatement(indexSelect);
-        closeStatement(nameInsert);
+        // closing the database resources is done by the owning
+        // BundleDbPersistenceManager that created this index
     }
 
     /**
@@ -135,11 +138,9 @@
      */
     protected int insertString(String string) {
         // assert index does not exist
-        PreparedStatement stmt = nameInsert;
         ResultSet rs = null;
         try {
-            stmt.setString(1, string);
-            stmt.executeUpdate();
+            Statement stmt = connectionManager.executeStmt(nameInsertSQL, new Object[]{string}, Statement.RETURN_GENERATED_KEYS);
             rs = stmt.getGeneratedKeys();
             if (!rs.next()) {
                 return -1;
@@ -150,7 +151,6 @@
             throw new IllegalStateException("Unable to insert index: " + e);
         } finally {
             closeResultSet(rs);
-            resetStatement(stmt);
         }
     }
 
@@ -160,11 +160,9 @@
      * @return the index or -1 if not found.
      */
     protected int getIndex(String string) {
-        PreparedStatement stmt = indexSelect;
         ResultSet rs = null;
         try {
-            stmt.setString(1, string);
-            stmt.execute();
+            Statement stmt = connectionManager.executeStmt(indexSelectSQL, new Object[]{string});
             rs = stmt.getResultSet();
             if (!rs.next()) {
                 return -1;
@@ -175,7 +173,6 @@
             throw new IllegalStateException("Unable to read index: " + e);
         } finally {
             closeResultSet(rs);
-            resetStatement(stmt);
         }
     }
 
@@ -185,11 +182,9 @@
      * @return the string or <code>null</code> if not found.
      */
     protected String getString(int index) {
-        PreparedStatement stmt = nameSelect;
         ResultSet rs = null;
         try {
-            stmt.setInt(1, index);
-            stmt.execute();
+            Statement stmt = connectionManager.executeStmt(nameSelectSQL, new Object[]{new Integer(index)});
             rs = stmt.getResultSet();
             if (!rs.next()) {
                 return null;
@@ -200,38 +195,6 @@
             throw new IllegalStateException("Unable to read name: " + e);
         } finally {
             closeResultSet(rs);
-            resetStatement(stmt);
-        }
-    }
-
-    /**
-     * closes the statement
-     * @param stmt the statement
-     */
-    protected void closeStatement(PreparedStatement stmt) {
-        if (stmt != null) {
-            try {
-                stmt.close();
-            } catch (SQLException se) {
-                // ignore
-            }
-        }
-    }
-    /**
-     * Resets the given <code>PreparedStatement</code> by clearing the
-     * parameters and warnings contained.
-     *
-     * @param stmt The <code>PreparedStatement</code> to reset. If
-     *             <code>null</code> this method does nothing.
-     */
-    protected void resetStatement(PreparedStatement stmt) {
-        if (stmt != null) {
-            try {
-                stmt.clearParameters();
-                stmt.clearWarnings();
-            } catch (SQLException se) {
-                // ignore
-            }
         }
     }
 
@@ -248,4 +211,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}

Modified: jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/NGKDbNameIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/NGKDbNameIndex.java?rev=631371&r1=631370&r2=631371&view=diff
==============================================================================
--- jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/NGKDbNameIndex.java (original)
+++ jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/NGKDbNameIndex.java Tue Feb 26 12:50:53 2008
@@ -16,11 +16,8 @@
  */
 package org.apache.jackrabbit.core.persistence.bundle.util;
 
-import java.sql.PreparedStatement;
 import java.sql.SQLException;
-import java.sql.Connection;
 import java.sql.ResultSet;
-import java.sql.Statement;
 
 /**
  * Same as {@link DbNameIndex} but does not make use of the
@@ -36,23 +33,23 @@
 
     /**
      * Creates a new index that is stored in a db.
-     * @param con the jdbc connection
+     * @param con the ConnectionRecoveryManager
      * @param schemaObjectPrefix the prefix for table names
      * @throws SQLException if the statements cannot be prepared.
      */
-    public NGKDbNameIndex(Connection con, String schemaObjectPrefix)
+    public NGKDbNameIndex(ConnectionRecoveryManager conMgr, String schemaObjectPrefix)
             throws SQLException {
-        super(con, schemaObjectPrefix);
+        super(conMgr, schemaObjectPrefix);
     }
 
     /**
      * {@inheritDoc}
      */
-    protected void init(Connection con, String schemaObjectPrefix)
+    protected void init(String schemaObjectPrefix)
             throws SQLException {
-        nameSelect = con.prepareStatement("select NAME from " + schemaObjectPrefix + "NAMES where ID = ?");
-        indexSelect = con.prepareStatement("select ID from " + schemaObjectPrefix + "NAMES where NAME = ?");
-        nameInsert = con.prepareStatement("insert into " + schemaObjectPrefix + "NAMES (NAME) values (?)");
+        nameSelectSQL = "select NAME from " + schemaObjectPrefix + "NAMES where ID = ?";
+        indexSelectSQL = "select ID from " + schemaObjectPrefix + "NAMES where NAME = ?";
+        nameInsertSQL = "insert into " + schemaObjectPrefix + "NAMES (NAME) values (?)";
     }
 
     /**
@@ -66,17 +63,14 @@
      */
     protected int insertString(String string) {
         // assert index does not exist
-        PreparedStatement stmt = nameInsert;
         ResultSet rs = null;
         try {
-            stmt.setString(1, string);
-            stmt.executeUpdate();
+            connectionManager.executeStmt(nameInsertSQL, new Object[]{string});
             return getIndex(string);
         } catch (Exception e) {
             throw new IllegalStateException("Unable to insert index: " + e);
         } finally {
             closeResultSet(rs);
-            resetStatement(stmt);
         }
     }
-}
\ No newline at end of file
+}



Mime
View raw message