Return-Path: Delivered-To: apmail-jackrabbit-commits-archive@www.apache.org Received: (qmail 55987 invoked from network); 8 Aug 2009 19:15:06 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 8 Aug 2009 19:15:06 -0000 Received: (qmail 1980 invoked by uid 500); 8 Aug 2009 19:15:13 -0000 Delivered-To: apmail-jackrabbit-commits-archive@jackrabbit.apache.org Received: (qmail 1898 invoked by uid 500); 8 Aug 2009 19:15:13 -0000 Mailing-List: contact commits-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@jackrabbit.apache.org Delivered-To: mailing list commits@jackrabbit.apache.org Received: (qmail 1888 invoked by uid 99); 8 Aug 2009 19:15:13 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 08 Aug 2009 19:15:13 +0000 X-ASF-Spam-Status: No, hits=-1998.9 required=10.0 tests=ALL_TRUSTED,FB_GET_MEDS X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 08 Aug 2009 19:15:10 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 52E682388853; Sat, 8 Aug 2009 19:14:50 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r802438 - in /jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle: ./ util/ Date: Sat, 08 Aug 2009 19:14:49 -0000 To: commits@jackrabbit.apache.org From: martijnh@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090808191450.52E682388853@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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()}. - *

- * Please note that this currently only needs to be changed for oracle based - * persistence managers. - * - * @return false - */ - 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()}.

Please note that this currently only needs to be changed for oracle + * based persistence managers. + * + * @return false + */ + 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; /** - * OracleLegacyPersistenceManager provides support for Oracle jdbc - * drivers prior to version 10 which require special handling of BLOB data. - *

- * Configuration:
+ * OracleLegacyPersistenceManager provides support for Oracle jdbc drivers prior to version 10 + * which require special handling of BLOB data.

Configuration:
*

    *
  • <param name="{@link #setBundleCacheSize(String) bundleCacheSize}" value="8"/> *
  • <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} - *

    - * Retrieve the oracle.sql.BLOB class via reflection, and - * initialize the values for the DURATION_SESSION and - * MODE_READWRITE 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 oracle.sql.BLOB class via reflection, and initialize the values for the + * DURATION_SESSION and MODE_READWRITE 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 tmpBlobs = new ArrayList(); + 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