You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ma...@apache.org on 2009/08/08 21:14:49 UTC

svn commit: r802438 - in /jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle: ./ util/

Author: martijnh
Date: Sat Aug  8 19:14:49 2009
New Revision: 802438

URL: http://svn.apache.org/viewvc?rev=802438&view=rev
Log:
JCR-1456 Database connection pooling

* Fixed the Oracle, H2 and PostgrSQL PMs (still needs testing)
* Moved DB specific code from Oracle PMs to the OracleConnectionHelper classes

Added:
    jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/Oracle10R1ConnectionHelper.java   (with props)
    jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/OracleConnectionHelper.java   (with props)
Modified:
    jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java
    jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/H2PersistenceManager.java
    jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/Oracle9PersistenceManager.java
    jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/OraclePersistenceManager.java
    jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/PostgreSQLPersistenceManager.java
    jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionHelper.java

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java?rev=802438&r1=802437&r2=802438&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java Sat Aug  8 19:14:49 2009
@@ -435,19 +435,6 @@
     }
 
     /**
-     * Indicates if the user name should be included when retrieving the tables
-     * during {@link #checkTablesExist()}.
-     * <p/>
-     * Please note that this currently only needs to be changed for oracle based
-     * persistence managers.
-     *
-     * @return <code>false</code>
-     */
-    public boolean checkTablesWithUser() {
-        return false;
-    }
-
-    /**
      * {@inheritDoc}
      *
      * Basically wraps a JDBC transaction around super.store().
@@ -518,14 +505,26 @@
      * {@link ConnectionHelper} instance. Subclasses may override it to return a specialized
      * connection helper.
      * 
-     * @param dataSrc the {@link DataSource} of this peristence manager
+     * @param dataSrc the {@link DataSource} of this persistence manager
      * @return a {@link ConnectionHelper}
+     * @throws Exception on error
      */
-    protected ConnectionHelper createConnectionHelper(DataSource dataSrc) {
+    protected ConnectionHelper createConnectionHelper(DataSource dataSrc) throws Exception {
         return new ConnectionHelper(dataSrc);
     }
 
     /**
+     * Indicates if the user name should be included when retrieving the tables during
+     * {@link #checkTablesExist()}. <p/> Please note that this currently only needs to be changed for oracle
+     * based persistence managers.
+     * 
+     * @return <code>false</code>
+     */
+    public boolean checkTablesWithUser() {
+        return false;
+    }
+
+    /**
      * {@inheritDoc}
      */
     protected BundleBinding getBinding() {

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/H2PersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/H2PersistenceManager.java?rev=802438&r1=802437&r2=802438&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/H2PersistenceManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/H2PersistenceManager.java Sat Aug  8 19:14:49 2009
@@ -16,14 +16,7 @@
  */
 package org.apache.jackrabbit.core.persistence.bundle;
 
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.Statement;
-
-import javax.jcr.RepositoryException;
-
 import org.apache.jackrabbit.core.persistence.PMContext;
-import org.apache.jackrabbit.core.persistence.bundle.util.ConnectionHelper;
 
 /**
  * Extends the {@link BundleDbPersistenceManager} by H2 specific code.
@@ -67,12 +60,6 @@
     }
 
     /**
-     * Creates a new H2 persistence manager.
-     */
-    public H2PersistenceManager() {
-    }
-
-    /**
      * {@inheritDoc}
      */
    public void init(PMContext context) throws Exception {
@@ -91,25 +78,8 @@
         }
 
         super.init(context);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void checkSchema() throws SQLException, RepositoryException {
-        // FIXME
-//    	Connection connection = null;
-//        Statement stmt = null;
-//        
-//        try {
-//        	connection = dataSource.getConnection();
-//        	stmt = connection.createStatement();
-//            stmt.execute("SET LOCK_TIMEOUT " + lockTimeout);
-//        } finally {
-//            ConnectionHelper.closeSilently(stmt);
-//            ConnectionHelper.closeSilently(connection);
-//        }
-//        super.checkSchema();
+        
+        conHelper.exec("SET LOCK_TIMEOUT " + lockTimeout);
     }
 
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/Oracle9PersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/Oracle9PersistenceManager.java?rev=802438&r1=802437&r2=802438&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/Oracle9PersistenceManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/Oracle9PersistenceManager.java Sat Aug  8 19:14:49 2009
@@ -16,35 +16,14 @@
  */
 package org.apache.jackrabbit.core.persistence.bundle;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.commons.io.IOUtils;
-import org.apache.jackrabbit.core.persistence.PMContext;
-import org.apache.jackrabbit.core.persistence.bundle.util.ConnectionHelper;
-import org.apache.jackrabbit.core.persistence.bundle.util.DbUtility;
-import org.apache.jackrabbit.core.persistence.bundle.util.NodePropBundle;
-import org.apache.jackrabbit.core.persistence.util.Serializer;
-import org.apache.jackrabbit.core.state.ItemStateException;
-import org.apache.jackrabbit.core.state.NodeReferences;
+import javax.sql.DataSource;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.reflect.Method;
-import java.sql.Blob;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
+import org.apache.jackrabbit.core.persistence.bundle.util.ConnectionHelper;
+import org.apache.jackrabbit.core.persistence.bundle.util.Oracle10R1ConnectionHelper;
 
 /**
- * <code>OracleLegacyPersistenceManager</code> provides support for Oracle jdbc
- * drivers prior to version 10 which require special handling of BLOB data.
- * <p/>
- * Configuration:<br>
+ * <code>OracleLegacyPersistenceManager</code> provides support for Oracle jdbc drivers prior to version 10
+ * which require special handling of BLOB data. <p/> Configuration:<br>
  * <ul>
  * <li>&lt;param name="{@link #setBundleCacheSize(String) bundleCacheSize}" value="8"/>
  * <li>&lt;param name="{@link #setConsistencyCheck(String) consistencyCheck}" value="false"/>
@@ -61,216 +40,12 @@
 public class Oracle9PersistenceManager extends OraclePersistenceManager {
 
     /**
-     * the default logger
-     */
-    private static Logger log = LoggerFactory.getLogger(Oracle9PersistenceManager.class);
-
-    private Class< ? > blobClass;
-    private Integer duractionSessionConstant;
-    private Integer modeReadWriteConstant;
-
-    public Oracle9PersistenceManager() {
-    }
-
-    //-----------------------------------< OraclePersistenceManager overrides >
-    /**
-     * {@inheritDoc}
-     * <p/>
-     * Retrieve the <code>oracle.sql.BLOB</code> class via reflection, and
-     * initialize the values for the <code>DURATION_SESSION</code> and
-     * <code>MODE_READWRITE</code> constants defined there.
-     *
-     * @see oracle.sql.BLOB#DURATION_SESSION
-     * @see oracle.sql.BLOB#MODE_READWRITE
-     */
-    public void init(PMContext context) throws Exception {
-        super.init(context);
-
-        // initialize oracle.sql.BLOB class & constants
-
-        // use the Connection object for using the exact same
-        // class loader that the Oracle driver was loaded with
-// FIXME        
-//        Connection connection = null;
-//        try {
-//        	connection = dataSource.getConnection();
-//        	blobClass = connection.getClass().getClassLoader().loadClass("oracle.sql.BLOB");
-//        } finally {
-//        	ConnectionHelper.closeSilently(connection);
-//        }
-        
-        duractionSessionConstant =
-                new Integer(blobClass.getField("DURATION_SESSION").getInt(null));
-        modeReadWriteConstant =
-                new Integer(blobClass.getField("MODE_READWRITE").getInt(null));
-    }
-
-    /**
-     * @inheritDoc
-     */
-    protected BundleDbPersistenceManager.CloseableBLOBStore createDBBlobStore(PMContext context) throws Exception {
-        return new OracleBLOBStore();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected synchronized void storeBundle(NodePropBundle bundle)
-            throws ItemStateException {
-        Blob blob = null;        
-        try {
-            ByteArrayOutputStream out = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
-            DataOutputStream dout = new DataOutputStream(out);
-            binding.writeBundle(dout, bundle);
-            dout.close();
-
-            String sql = bundle.isNew() ? bundleInsertSQL : bundleUpdateSQL;
-            blob = createTemporaryBlob(new ByteArrayInputStream(out.toByteArray()));
-            Object[] params = createParams(bundle.getId(), blob, true);
-            conHelper.exec(sql, params);
-        } catch (Exception e) {
-            String msg = "failed to write bundle: " + bundle.getId();
-            log.error(msg, e);
-            throw new ItemStateException(msg, e);
-        } finally {
-            if (blob != null) {
-                try {
-                    freeTemporaryBlob(blob);
-                } catch (Exception e1) {
-                }
-            }
-        }
-    }
-
-    /**
      * {@inheritDoc}
      */
     @Override
-    public synchronized void store(NodeReferences refs)
-            throws ItemStateException {
-        if (!initialized) {
-            throw new IllegalStateException("not initialized");
-        }
-
-        Blob blob = null;
-        try {
-            // check if insert or update
-            boolean update = existsReferencesTo(refs.getTargetId());
-            String sql = (update) ? nodeReferenceUpdateSQL : nodeReferenceInsertSQL;
-
-            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
-
-            blob = createTemporaryBlob(new ByteArrayInputStream(out.toByteArray()));
-            Object[] params = createParams(refs.getTargetId(), blob, true);
-            conHelper.exec(sql, params);
-
-            // there's no need to close a ByteArrayOutputStream
-            //out.close();
-        } catch (Exception e) {
-            String msg = "failed to write " + refs;
-            log.error(msg, e);
-            throw new ItemStateException(msg, e);
-        } finally {
-            if (blob != null) {
-                try {
-                    freeTemporaryBlob(blob);
-                } catch (Exception e1) {
-                }
-            }
-        }
-    }
-
-    //----------------------------------------< oracle-specific blob handling >
-    /**
-     * Creates a temporary oracle.sql.BLOB instance via reflection and spools
-     * the contents of the specified stream.
-     */
-    protected Blob createTemporaryBlob(InputStream in) throws Exception {
-        /*
-        BLOB blob = BLOB.createTemporary(con, false, BLOB.DURATION_SESSION);
-        blob.open(BLOB.MODE_READWRITE);
-        OutputStream out = blob.getBinaryOutputStream();
-        ...
-        out.flush();
-        out.close();
-        blob.close();
-        return blob;
-        */
-// FIXME
-//        Method createTemporary = blobClass.getMethod("createTemporary",
-//                new Class[]{Connection.class, Boolean.TYPE, Integer.TYPE});
-//        Object blob = createTemporary.invoke(null,
-//                new Object[]{context.getConnection(), Boolean.FALSE, duractionSessionConstant});
-//        Method open = blobClass.getMethod("open", new Class[]{Integer.TYPE});
-//        open.invoke(blob, new Object[]{modeReadWriteConstant});
-//        Method getBinaryOutputStream = blobClass.getMethod("getBinaryOutputStream", new Class[0]);
-//        OutputStream out = (OutputStream) getBinaryOutputStream.invoke(blob);
-//        try {
-//            IOUtils.copy(in, out);
-//        } finally {
-//            try {
-//                out.flush();
-//            } catch (IOException ioe) {
-//            }
-//            out.close();
-//        }
-//        Method close = blobClass.getMethod("close", new Class[0]);
-//        close.invoke(blob);
-//        return (Blob) blob;
-        return null;
-    }
-
-    /**
-     * Frees a temporary oracle.sql.BLOB instance via reflection.
-     */
-    protected void freeTemporaryBlob(Object blob) throws Exception {
-        // blob.freeTemporary();
-        Method freeTemporary = blobClass.getMethod("freeTemporary", new Class[0]);
-        freeTemporary.invoke(blob);
-    }
-
-    /**
-     * A blob store specially for Oracle 9.
-     */
-    class OracleBLOBStore extends DbBlobStore {
-
-        public OracleBLOBStore() throws SQLException {
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public synchronized void put(String blobId, InputStream in, long size)
-                throws Exception {
-
-            Blob blob = null;
-            try {
-                boolean exists = false;
-                ResultSet rs = null;
-                try {
-                    conHelper.exec(blobSelectExistSQL, new Object[]{blobId}, false, 0);
-                    // a BLOB exists if the result has at least one entry
-                    exists = rs.next();
-                } finally {
-                    DbUtility.close(rs);
-                }
-
-                String sql = (exists) ? blobUpdateSQL : blobInsertSQL;
-                blob = createTemporaryBlob(in);
-                conHelper.exec(sql, new Object[]{blob, blobId});
-            } finally {
-                if (blob != null) {
-                    try {
-                        freeTemporaryBlob(blob);
-                    } catch (Exception e) {
-                    }
-                }
-            }
-        }
+    protected ConnectionHelper createConnectionHelper(DataSource dataSrc) throws Exception {
+        Oracle10R1ConnectionHelper helper =  new Oracle10R1ConnectionHelper(dataSrc);
+        helper.init();
+        return helper;
     }
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/OraclePersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/OraclePersistenceManager.java?rev=802438&r1=802437&r2=802438&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/OraclePersistenceManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/OraclePersistenceManager.java Sat Aug  8 19:14:49 2009
@@ -16,17 +16,16 @@
  */
 package org.apache.jackrabbit.core.persistence.bundle;
 
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 
+import javax.sql.DataSource;
+
 import org.apache.jackrabbit.core.persistence.PMContext;
 import org.apache.jackrabbit.core.persistence.bundle.util.ConnectionHelper;
 import org.apache.jackrabbit.core.persistence.bundle.util.DbNameIndex;
 import org.apache.jackrabbit.core.persistence.bundle.util.NGKDbNameIndex;
+import org.apache.jackrabbit.core.persistence.bundle.util.OracleConnectionHelper;
 import org.apache.jackrabbit.util.Text;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Extends the {@link BundleDbPersistenceManager} by Oracle specific code.
@@ -49,11 +48,6 @@
  */
 public class OraclePersistenceManager extends BundleDbPersistenceManager {
 
-    /**
-     * the default logger
-     */
-    private static Logger log = LoggerFactory.getLogger(OraclePersistenceManager.class);
-
     /** the variable for the Oracle table space */
     public static final String TABLE_SPACE_VARIABLE =
         "${tableSpace}";
@@ -104,24 +98,6 @@
             setSchemaObjectPrefix(context.getHomeDir().getName() + "_");
         }
         super.init(context);
-
-        // check driver version
-        // FIXME
-//        Connection connection = dataSource.getConnection();
-//        try {
-//            DatabaseMetaData metaData = connection.getMetaData();
-//            if (metaData.getDriverMajorVersion() < 10) {
-//                // Oracle drivers prior to version 10 only support
-//                // writing BLOBs up to 32k in size...
-//                log.warn("Unsupported driver version detected: "
-//                        + metaData.getDriverName()
-//                        + " v" + metaData.getDriverVersion());
-//            }
-//        } catch (SQLException e) {
-//            log.warn("Can not retrieve driver version", e);
-//        } finally {
-//        	ConnectionHelper.closeSilently(connection);
-//        }
     }
 
     /**
@@ -129,10 +105,9 @@
      * @return a new instance of a NGKDbNameIndex.
      * @throws SQLException if an SQL error occurs.
      */
-// FIXME
-//    protected DbNameIndex createDbNameIndex() throws SQLException {
-//        return new NGKDbNameIndex(dataSource, schemaObjectPrefix);
-//    }
+    protected DbNameIndex createDbNameIndex() throws SQLException {
+        return new NGKDbNameIndex(conHelper, schemaObjectPrefix);
+    }
 
     /**
      * {@inheritDoc}
@@ -160,36 +135,12 @@
     }
 
     /**
-     * Since Oracle only supports table names up to 30 characters in
-     * length illegal characters are simply replaced with "_" rather than
-     * escaping them with "_x0000_".
-     *
-     * @inheritDoc
+     * {@inheritDoc}
      */
-// FIXME
-//    protected void prepareSchemaObjectPrefix() throws Exception {
-//        String legalChars;
-//        Connection connection = null;
-//        try {
-//        	connection = dataSource.getConnection();
-//        	DatabaseMetaData metaData = connection.getMetaData();
-//        	legalChars = metaData.getExtraNameCharacters();
-//        } finally {
-//        	ConnectionHelper.closeSilently(connection);
-//        }        	
-//        
-//        legalChars += "ABCDEFGHIJKLMNOPQRSTUVWXZY0123456789_";
-//
-//        String prefix = schemaObjectPrefix.toUpperCase();
-//        StringBuffer escaped = new StringBuffer();
-//        for (int i = 0; i < prefix.length(); i++) {
-//            char c = prefix.charAt(i);
-//            if (legalChars.indexOf(c) == -1) {
-//                escaped.append('_');
-//            } else {
-//                escaped.append(c);
-//            }
-//        }
-//        schemaObjectPrefix = escaped.toString();
-//    }
+    @Override
+    protected ConnectionHelper createConnectionHelper(DataSource dataSrc) throws Exception {
+        OracleConnectionHelper helper =  new OracleConnectionHelper(dataSrc);
+        helper.init();
+        return helper;
+    }
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/PostgreSQLPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/PostgreSQLPersistenceManager.java?rev=802438&r1=802437&r2=802438&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/PostgreSQLPersistenceManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/PostgreSQLPersistenceManager.java Sat Aug  8 19:14:49 2009
@@ -20,11 +20,11 @@
 import java.io.InputStream;
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.sql.Statement;
 
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.persistence.PMContext;
 import org.apache.jackrabbit.core.persistence.bundle.util.DbNameIndex;
+import org.apache.jackrabbit.core.persistence.bundle.util.DbUtility;
 import org.apache.jackrabbit.core.persistence.bundle.util.NodePropBundle;
 import org.apache.jackrabbit.core.persistence.bundle.util.PostgreSQLNameIndex;
 import org.apache.jackrabbit.core.persistence.bundle.util.TrackingInputStream;
@@ -76,10 +76,9 @@
      * @return a new instance of a DbNameIndex.
      * @throws java.sql.SQLException if an SQL error occurs.
      */
-// FIXME
-//    protected DbNameIndex createDbNameIndex() throws SQLException {
-//        return new PostgreSQLNameIndex(dataSource, schemaObjectPrefix);
-//    }
+    protected DbNameIndex createDbNameIndex() throws SQLException {
+        return new PostgreSQLNameIndex(conHelper, schemaObjectPrefix);
+    }
 
     /**
      * returns the storage model
@@ -89,39 +88,38 @@
         return SM_LONGLONG_KEYS;
     }
 
- // FIXME
-//
-//    protected synchronized NodePropBundle loadBundle(NodeId id)
-//            throws ItemStateException {
-//    	BundleDbContext context = createContext();
-//        try {        	
-//            Statement stmt = context.getConnectionHelper().executeStmt(bundleSelectSQL, getKey(id));
-//            ResultSet rs = stmt.getResultSet();
-//            try {
-//                if (rs.next()) {
-//                    InputStream input = rs.getBinaryStream(1);
-//                    try {
-//                        TrackingInputStream cin = new TrackingInputStream(input);
-//                        DataInputStream din = new DataInputStream(cin);
-//                        NodePropBundle bundle = binding.readBundle(din, id);
-//                        bundle.setSize(cin.getPosition());
-//                        return bundle;
-//                    } finally {
-//                        input.close();
-//                    }
-//                } else {
-//                    return null;
-//                }
-//            } finally {
-//                rs.close();
-//            }
-//        } catch (Exception e) {
-//            String msg = "failed to read bundle: " + id + ": " + e;
-//            log.error(msg);
-//            throw new ItemStateException(msg, e);
-//        } finally {
-//        	context.closeSilently();
-//        }
-//    }
+    /**
+     * PostgreSQL needs slightly different handling of the binary value that is received:
+     * rs.getBinaryStream vs rs.getBlob in the super class.
+     * 
+     * {@inheritDoc}
+     */
+    protected synchronized NodePropBundle loadBundle(NodeId id)
+            throws ItemStateException {
+        ResultSet rs = null;
+        try {        	
+            rs = conHelper.exec(bundleSelectSQL, getKey(id), false, 0);
+            if (rs.next()) {
+                InputStream input = rs.getBinaryStream(1);
+                try {
+                    TrackingInputStream cin = new TrackingInputStream(input);
+                    DataInputStream din = new DataInputStream(cin);
+                    NodePropBundle bundle = binding.readBundle(din, id);
+                    bundle.setSize(cin.getPosition());
+                    return bundle;
+                } finally {
+                    input.close();
+                }
+            } else {
+                return null;
+            }
+        } catch (Exception e) {
+            String msg = "failed to read bundle: " + id + ": " + e;
+            log.error(msg);
+            throw new ItemStateException(msg, e);
+        } finally {
+           DbUtility.close(rs);
+        }
+    }
 
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionHelper.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionHelper.java?rev=802438&r1=802437&r2=802438&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionHelper.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionHelper.java Sat Aug  8 19:14:49 2009
@@ -91,11 +91,7 @@
         for (int i = 0; i < id.length(); i++) {
             char c = id.charAt(i);
             if (legalChars.indexOf(c) == -1) {
-                escaped.append("_x");
-                String hex = Integer.toHexString(c);
-                escaped.append("0000".toCharArray(), 0, 4 - hex.length());
-                escaped.append(hex);
-                escaped.append("_");
+                replaceCharacter(escaped, c);
             } else {
                 escaped.append(c);
             }
@@ -104,13 +100,27 @@
     }
 
     /**
-     * The default implementation returns the {@code extraNameCharacters} provided by the
-     * databases metadata.
+     * Called from {@link #prepareDbIdentifier(String)}. Default implementation replaces the illegal
+     * characters with their hexadecimal encoding.
+     * 
+     * @param escaped the escaped db identifier
+     * @param c the character to replace
+     */
+    protected void replaceCharacter(StringBuffer escaped, char c) {
+        escaped.append("_x");
+        String hex = Integer.toHexString(c);
+        escaped.append("0000".toCharArray(), 0, 4 - hex.length());
+        escaped.append(hex);
+        escaped.append("_");
+    }
+
+    /**
+     * The default implementation returns the {@code extraNameCharacters} provided by the databases metadata.
      * 
      * @return the additional characters for identifiers supported by the db
      * @throws SQLException on error
      */
-    protected String getExtraNameCharacters() throws SQLException {
+    private String getExtraNameCharacters() throws SQLException {
         Connection con = dataSource.getConnection();
         try {
             DatabaseMetaData metaData = con.getMetaData();
@@ -239,7 +249,7 @@
      * @param params the parameters for the SQL statement
      * @throws SQLException on error
      */
-    public final void exec(String sql, Object...params) throws SQLException {
+    public final void exec(String sql, Object... params) throws SQLException {
         Connection con = null;
         PreparedStatement stmt = null;
         try {
@@ -317,9 +327,9 @@
     }
 
     /**
-     * Gets a connection based on the {@code batchMode} state of this helper. The connection
-     * should be closed by a call to {@link #closeResources(Connection, Statement, ResultSet)} which
-     * also takes the {@code batchMode} state into account.
+     * Gets a connection based on the {@code batchMode} state of this helper. The connection should be closed
+     * by a call to {@link #closeResources(Connection, Statement, ResultSet)} which also takes the {@code
+     * batchMode} state into account.
      * 
      * @return a {@code Connection} to use, based on the batch mode state
      * @throws SQLException on error
@@ -353,12 +363,17 @@
     }
 
     /**
-     * @param stmt
-     * @param params
-     * @return
-     * @throws SQLException
+     * This method is used by all methods of this class that execute SQL statements. This default
+     * implementation sets all parameters and unwraps {@link StreamWrapper} instances. Subclasses may override
+     * this method to do something special with the parameters. E.g., the {@code Oracle10R1ConnectionHelper}
+     * overrides it in order to add special blob handling.
+     * 
+     * @param stmt the {@link PreparedStatement} to execute
+     * @param params the parameters
+     * @return the executed statement
+     * @throws SQLException on error
      */
-    private PreparedStatement execute(PreparedStatement stmt, Object[] params) throws SQLException {
+    protected PreparedStatement execute(PreparedStatement stmt, Object[] params) throws SQLException {
         for (int i = 0; params != null && i < params.length; i++) {
             Object p = params[i];
             if (p instanceof StreamWrapper) {

Added: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/Oracle10R1ConnectionHelper.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/Oracle10R1ConnectionHelper.java?rev=802438&view=auto
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/Oracle10R1ConnectionHelper.java (added)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/Oracle10R1ConnectionHelper.java Sat Aug  8 19:14:49 2009
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.jackrabbit.core.persistence.bundle.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Method;
+import java.sql.Blob;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.sql.DataSource;
+
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The connection helper for Oracle databases of version up to 10.1. It has special blob handling.
+ */
+public final class Oracle10R1ConnectionHelper extends OracleConnectionHelper {
+
+    /**
+     * the default logger
+     */
+    private static Logger log = LoggerFactory.getLogger(Oracle10R1ConnectionHelper.class);
+
+    private Class<?> blobClass;
+
+    private Integer durationSessionConstant;
+
+    private Integer modeReadWriteConstant;
+
+    /**
+     * @param dataSrc
+     */
+    public Oracle10R1ConnectionHelper(DataSource dataSrc) {
+        super(dataSrc);
+    }
+
+    /**
+     * Retrieve the <code>oracle.sql.BLOB</code> class via reflection, and initialize the values for the
+     * <code>DURATION_SESSION</code> and <code>MODE_READWRITE</code> constants defined there.
+     * 
+     * @see oracle.sql.BLOB#DURATION_SESSION
+     * @see oracle.sql.BLOB#MODE_READWRITE
+     */
+    public void init() throws Exception {
+        super.init();
+        // initialize oracle.sql.BLOB class & constants
+
+        // use the Connection object for using the exact same
+        // class loader that the Oracle driver was loaded with
+        Connection con = null;
+        try {
+            con = dataSource.getConnection();
+            blobClass = con.getClass().getClassLoader().loadClass("oracle.sql.BLOB");
+            durationSessionConstant = new Integer(blobClass.getField("DURATION_SESSION").getInt(null));
+            modeReadWriteConstant = new Integer(blobClass.getField("MODE_READWRITE").getInt(null));
+        } finally {
+            if (con != null) {
+                DbUtility.close(con, null, null);
+            }
+        }
+    }
+
+    /**
+     * Wraps any input-stream parameters in temporary blobs and frees these again after the statement
+     * has been executed.
+     * 
+     * {@inheritDoc}
+     */
+    @Override
+    protected PreparedStatement execute(PreparedStatement stmt, Object[] params) throws SQLException {
+        List<Blob> tmpBlobs = new ArrayList<Blob>();
+        try {
+            for (int i = 0; params != null && i < params.length; i++) {
+                Object p = params[i];
+                if (p instanceof StreamWrapper) {
+                    StreamWrapper wrapper = (StreamWrapper) p;
+                    Blob tmp = createTemporaryBlob(stmt.getConnection(), wrapper.getStream());
+                    tmpBlobs.add(tmp);
+                    stmt.setObject(i + 1, tmp);
+                } else if (p instanceof InputStream) {
+                    Blob tmp = createTemporaryBlob(stmt.getConnection(), (InputStream) p);
+                    tmpBlobs.add(tmp);
+                    stmt.setObject(i + 1, tmp);
+                } else {
+                    stmt.setObject(i + 1, p);
+                }
+            }
+            stmt.execute();
+            return stmt;
+        } catch (Exception e) {
+            throw new SQLException(e.getMessage());
+        } finally {
+            for (Blob blob : tmpBlobs) {
+                try {
+                    freeTemporaryBlob(blob);
+                } catch (Exception e) {
+                    log.warn("Could not close temporary blob", e);
+                }
+            }
+        }
+    }
+
+    /**
+     * Creates a temporary oracle.sql.BLOB instance via reflection and spools the contents of the specified
+     * stream.
+     */
+    private Blob createTemporaryBlob(Connection con, InputStream in) throws Exception {
+        /*
+         * BLOB blob = BLOB.createTemporary(con, false, BLOB.DURATION_SESSION);
+         * blob.open(BLOB.MODE_READWRITE); OutputStream out = blob.getBinaryOutputStream(); ... out.flush();
+         * out.close(); blob.close(); return blob;
+         */
+        Method createTemporary =
+            blobClass.getMethod("createTemporary", new Class[]{Connection.class, Boolean.TYPE, Integer.TYPE});
+        Object blob = createTemporary.invoke(null, new Object[]{con, Boolean.FALSE, durationSessionConstant});
+        Method open = blobClass.getMethod("open", new Class[]{Integer.TYPE});
+        open.invoke(blob, new Object[]{modeReadWriteConstant});
+        Method getBinaryOutputStream = blobClass.getMethod("getBinaryOutputStream", new Class[0]);
+        OutputStream out = (OutputStream) getBinaryOutputStream.invoke(blob);
+        try {
+            IOUtils.copy(in, out);
+        } finally {
+            try {
+                out.flush();
+            } catch (IOException ioe) {
+            }
+            out.close();
+        }
+        Method close = blobClass.getMethod("close", new Class[0]);
+        close.invoke(blob);
+        return (Blob) blob;
+    }
+
+    /**
+     * Frees a temporary oracle.sql.BLOB instance via reflection.
+     */
+    private void freeTemporaryBlob(Blob blob) throws Exception {
+        // blob.freeTemporary();
+        Method freeTemporary = blobClass.getMethod("freeTemporary", new Class[0]);
+        freeTemporary.invoke(blob);
+    }
+}

Propchange: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/Oracle10R1ConnectionHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/OracleConnectionHelper.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/OracleConnectionHelper.java?rev=802438&view=auto
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/OracleConnectionHelper.java (added)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/OracleConnectionHelper.java Sat Aug  8 19:14:49 2009
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.jackrabbit.core.persistence.bundle.util;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+
+import javax.sql.DataSource;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The connection helper for Oracle databases of version 10.2 and later.
+ */
+public class OracleConnectionHelper extends ConnectionHelper {
+
+    /**
+     * the default logger
+     */
+    private static Logger log = LoggerFactory.getLogger(OracleConnectionHelper.class);
+
+    /**
+     * @param dataSrc
+     */
+    public OracleConnectionHelper(DataSource dataSrc) {
+        super(dataSrc);
+    }
+
+    public void init() throws Exception {
+         // check driver version
+        Connection connection = dataSource.getConnection();
+        try {
+            DatabaseMetaData metaData = connection.getMetaData();
+            if (metaData.getDriverMajorVersion() < 10) {
+                // Oracle drivers prior to version 10 only support
+                // writing BLOBs up to 32k in size...
+                log.warn("Unsupported driver version detected: "
+                        + metaData.getDriverName()
+                        + " v" + metaData.getDriverVersion());
+            }
+        } catch (SQLException e) {
+            log.warn("Can not retrieve driver version", e);
+        } finally {
+          DbUtility.close(connection, null, null);
+        }
+    }
+
+    /**
+     * Since Oracle only supports table names up to 30 characters in
+     * length illegal characters are simply replaced with "_" rather than
+     * escaping them with "_x0000_".
+     *
+     * {@inheritDoc}
+     */
+    @Override
+    protected void replaceCharacter(StringBuffer escaped, char c) {
+        escaped.append("_");
+    }
+}

Propchange: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/OracleConnectionHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native