Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/DatabaseFileSystem.java =================================================================== --- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/DatabaseFileSystem.java (revision 483490) +++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/DatabaseFileSystem.java (working copy) @@ -16,18 +16,9 @@ */ package org.apache.jackrabbit.core.fs.db; -import org.apache.jackrabbit.core.fs.FileSystem; -import org.apache.jackrabbit.core.fs.FileSystemException; -import org.apache.jackrabbit.core.fs.FileSystemPathUtil; -import org.apache.jackrabbit.core.fs.RandomAccessOutputStream; -import org.apache.jackrabbit.util.Text; -import org.apache.jackrabbit.util.TransientFileFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jcr.RepositoryException; import java.io.BufferedReader; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FilterInputStream; import java.io.FilterOutputStream; @@ -35,7 +26,6 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; -import java.io.FileInputStream; import java.io.RandomAccessFile; import java.sql.Connection; import java.sql.DatabaseMetaData; @@ -44,9 +34,20 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; -import java.util.HashMap; +import javax.jcr.RepositoryException; + +import org.apache.jackrabbit.core.fs.FileSystem; +import org.apache.jackrabbit.core.fs.FileSystemException; +import org.apache.jackrabbit.core.fs.FileSystemPathUtil; +import org.apache.jackrabbit.core.fs.RandomAccessOutputStream; +import org.apache.jackrabbit.util.Text; +import org.apache.jackrabbit.util.TransientFileFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Base class for database file systems. This class contains common * functionality for database file system subclasses that normally differ only @@ -64,12 +65,13 @@ */ private static Logger log = LoggerFactory.getLogger(DbFileSystem.class); - protected static final String SCHEMA_OBJECT_PREFIX_VARIABLE = - "${schemaObjectPrefix}"; + protected static final String SCHEMA_OBJECT_PREFIX_VARIABLE = "${schema" + + "ObjectPrefix}"; protected boolean initialized; protected String schema; + protected String schemaObjectPrefix; // initial size of buffer used to serialize objects @@ -86,22 +88,39 @@ // SQL statements protected String selectExistSQL; + protected String selectFileExistSQL; + protected String selectFolderExistSQL; + protected String selectChildCountSQL; + protected String selectDataSQL; + protected String selectLastModifiedSQL; + protected String selectLengthSQL; + protected String selectFileNamesSQL; + protected String selectFolderNamesSQL; + protected String selectFileAndFolderNamesSQL; + protected String deleteFileSQL; + protected String deleteFolderSQL; + protected String insertFileSQL; + protected String insertFolderSQL; + protected String updateDataSQL; + protected String updateLastModifiedSQL; + protected String copyFileSQL; + protected String copyFilesSQL; /** @@ -113,7 +132,7 @@ initialized = false; } - //----------------------------------------------------< setters & getters > + // ----------------------------------------------------< setters & getters > public String getSchemaObjectPrefix() { return schemaObjectPrefix; } @@ -131,7 +150,7 @@ this.schema = schema; } - //-------------------------------------------< java.lang.Object overrides > + // -------------------------------------------< java.lang.Object overrides > /** * {@inheritDoc} */ @@ -141,8 +160,11 @@ } if (obj instanceof DatabaseFileSystem) { DatabaseFileSystem other = (DatabaseFileSystem) obj; - if (((schema != null) ? schema.equals(other.schema) : other.schema == null) - && ((schemaObjectPrefix != null) ? schemaObjectPrefix.equals(other.schemaObjectPrefix) : other.schemaObjectPrefix == null)) { + if (((schema != null) ? schema.equals(other.schema) + : other.schema == null) + && ((schemaObjectPrefix != null) ? schemaObjectPrefix + .equals(other.schemaObjectPrefix) + : other.schemaObjectPrefix == null)) { return true; } } @@ -150,8 +172,8 @@ } /** - * Returns zero to satisfy the Object equals/hashCode contract. - * This class is mutable and not meant to be used as a hash key. + * Returns zero to satisfy the Object equals/hashCode contract. This class + * is mutable and not meant to be used as a hash key. * * @return always zero * @see Object#hashCode() @@ -160,7 +182,7 @@ return 0; } - //-----------------------------------------------------------< FileSystem > + // -----------------------------------------------------------< FileSystem > /** * {@inheritDoc} @@ -174,7 +196,8 @@ // setup jdbc connection initConnection(); - // make sure schemaObjectPrefix consists of legal name characters only + // make sure schemaObjectPrefix consists of legal name characters + // only prepareSchemaObjectPrefix(); // check if schema objects exist and create them if necessary @@ -207,7 +230,8 @@ try { // close shared prepared statements - for (Iterator it = preparedStatements.values().iterator(); it.hasNext(); ) { + for (Iterator it = preparedStatements.values().iterator(); it + .hasNext();) { closeStatement((PreparedStatement) it.next()); } preparedStatements.clear(); @@ -236,7 +260,8 @@ if (!exists(folderPath)) { createDeepFolder(folderPath); } else { - throw new FileSystemException("file system entry already exists: " + folderPath); + throw new FileSystemException("file system entry already exists: " + + folderPath); } } @@ -256,8 +281,8 @@ int count = 0; synchronized (deleteFileSQL) { try { - Statement stmt = executeStmt( - deleteFileSQL, new Object[]{parentDir, name}); + Statement stmt = executeStmt(deleteFileSQL, new Object[] { + parentDir, name}); count = stmt.getUpdateCount(); } catch (SQLException e) { String msg = "failed to delete file: " + filePath; @@ -291,10 +316,8 @@ int count = 0; synchronized (deleteFolderSQL) { try { - Statement stmt = executeStmt(deleteFolderSQL, new Object[]{ - parentDir, - name, - folderPath, + Statement stmt = executeStmt(deleteFolderSQL, new Object[] { + parentDir, name, folderPath, folderPath + FileSystem.SEPARATOR + "%"}); count = stmt.getUpdateCount(); } catch (SQLException e) { @@ -325,15 +348,16 @@ synchronized (selectExistSQL) { ResultSet rs = null; try { - Statement stmt = executeStmt( - selectExistSQL, new Object[]{parentDir, name}); + Statement stmt = executeStmt(selectExistSQL, new Object[] { + parentDir, name}); rs = stmt.getResultSet(); // a file system entry exists if the result set // has at least one entry return rs.next(); } catch (SQLException e) { - String msg = "failed to check existence of file system entry: " + path; + String msg = "failed to check existence of file system entry: " + + path; log.error(msg, e); throw new FileSystemException(msg, e); } finally { @@ -358,8 +382,8 @@ synchronized (selectFileExistSQL) { ResultSet rs = null; try { - Statement stmt = executeStmt( - selectFileExistSQL, new Object[]{parentDir, name}); + Statement stmt = executeStmt(selectFileExistSQL, new Object[] { + parentDir, name}); rs = stmt.getResultSet(); // a file exists if the result set has at least one entry @@ -390,8 +414,8 @@ synchronized (selectFolderExistSQL) { ResultSet rs = null; try { - Statement stmt = executeStmt( - selectFolderExistSQL, new Object[]{parentDir, name}); + Statement stmt = executeStmt(selectFolderExistSQL, + new Object[] {parentDir, name}); rs = stmt.getResultSet(); // a folder exists if the result set has at least one entry @@ -422,15 +446,17 @@ synchronized (selectLastModifiedSQL) { ResultSet rs = null; try { - Statement stmt = executeStmt( - selectLastModifiedSQL, new Object[]{parentDir, name}); + Statement stmt = executeStmt(selectLastModifiedSQL, + new Object[] {parentDir, name}); rs = stmt.getResultSet(); if (!rs.next()) { - throw new FileSystemException("no such file system entry: " + path); + throw new FileSystemException("no such file system entry: " + + path); } return rs.getLong(1); } catch (SQLException e) { - String msg = "failed to determine lastModified of file system entry: " + path; + String msg = "failed to determine lastModified of file system " + + "entry: " + path; log.error(msg, e); throw new FileSystemException(msg, e); } finally { @@ -455,8 +481,8 @@ synchronized (selectLengthSQL) { ResultSet rs = null; try { - Statement stmt = executeStmt( - selectLengthSQL, new Object[]{parentDir, name}); + Statement stmt = executeStmt(selectLengthSQL, new Object[] { + parentDir, name}); rs = stmt.getResultSet(); if (!rs.next()) { throw new FileSystemException("no such file: " + filePath); @@ -489,7 +515,8 @@ synchronized (selectChildCountSQL) { ResultSet rs = null; try { - Statement stmt = executeStmt(selectChildCountSQL, new Object[]{path}); + Statement stmt = executeStmt(selectChildCountSQL, + new Object[] {path}); rs = stmt.getResultSet(); if (!rs.next()) { return false; @@ -501,7 +528,8 @@ } return (count > 0); } catch (SQLException e) { - String msg = "failed to determine child count of file system entry: " + path; + String msg = "failed to determine child count of file system " + + "entry: " + path; log.error(msg, e); throw new FileSystemException(msg, e); } finally { @@ -527,8 +555,8 @@ synchronized (selectFileAndFolderNamesSQL) { ResultSet rs = null; try { - Statement stmt = executeStmt( - selectFileAndFolderNamesSQL, new Object[]{folderPath}); + Statement stmt = executeStmt(selectFileAndFolderNamesSQL, + new Object[] {folderPath}); rs = stmt.getResultSet(); ArrayList names = new ArrayList(); while (rs.next()) { @@ -542,7 +570,8 @@ } return (String[]) names.toArray(new String[names.size()]); } catch (SQLException e) { - String msg = "failed to list child entries of folder: " + folderPath; + String msg = "failed to list child entries of folder: " + + folderPath; log.error(msg, e); throw new FileSystemException(msg, e); } finally { @@ -568,8 +597,8 @@ synchronized (selectFileNamesSQL) { ResultSet rs = null; try { - Statement stmt = executeStmt( - selectFileNamesSQL, new Object[]{folderPath}); + Statement stmt = executeStmt(selectFileNamesSQL, + new Object[] {folderPath}); rs = stmt.getResultSet(); ArrayList names = new ArrayList(); while (rs.next()) { @@ -577,7 +606,8 @@ } return (String[]) names.toArray(new String[names.size()]); } catch (SQLException e) { - String msg = "failed to list file entries of folder: " + folderPath; + String msg = "failed to list file entries of folder: " + + folderPath; log.error(msg, e); throw new FileSystemException(msg, e); } finally { @@ -603,8 +633,8 @@ synchronized (selectFolderNamesSQL) { ResultSet rs = null; try { - Statement stmt = executeStmt( - selectFolderNamesSQL, new Object[]{folderPath}); + Statement stmt = executeStmt(selectFolderNamesSQL, + new Object[] {folderPath}); rs = stmt.getResultSet(); ArrayList names = new ArrayList(); while (rs.next()) { @@ -618,7 +648,8 @@ } return (String[]) names.toArray(new String[names.size()]); } catch (SQLException e) { - String msg = "failed to list folder entries of folder: " + folderPath; + String msg = "failed to list folder entries of folder: " + + folderPath; log.error(msg, e); throw new FileSystemException(msg, e); } finally { @@ -643,10 +674,9 @@ int count = 0; synchronized (updateLastModifiedSQL) { try { - Statement stmt = executeStmt(updateLastModifiedSQL, new Object[]{ - new Long(System.currentTimeMillis()), - parentDir, - name}); + Statement stmt = executeStmt(updateLastModifiedSQL, + new Object[] {new Long(System.currentTimeMillis()), + parentDir, name}); count = stmt.getUpdateCount(); } catch (SQLException e) { String msg = "failed to touch file: " + filePath; @@ -663,7 +693,8 @@ /** * {@inheritDoc} */ - public InputStream getInputStream(String filePath) throws FileSystemException { + public InputStream getInputStream(String filePath) + throws FileSystemException { if (!initialized) { throw new IllegalStateException("not initialized"); } @@ -675,8 +706,8 @@ synchronized (selectDataSQL) { try { - Statement stmt = executeStmt( - selectDataSQL, new Object[]{parentDir, name}); + Statement stmt = executeStmt(selectDataSQL, new Object[] { + parentDir, name}); final ResultSet rs = stmt.getResultSet(); if (!rs.next()) { @@ -684,8 +715,8 @@ } InputStream in = rs.getBinaryStream(1); /** - * return an InputStream wrapper in order to - * close the ResultSet when the stream is closed + * return an InputStream wrapper in order to close the ResultSet + * when the stream is closed */ return new FilterInputStream(in) { public void close() throws IOException { @@ -725,8 +756,10 @@ } try { - TransientFileFactory fileFactory = TransientFileFactory.getInstance(); - final File tmpFile = fileFactory.createTransientFile("bin", null, null); + TransientFileFactory fileFactory = TransientFileFactory + .getInstance(); + final File tmpFile = fileFactory.createTransientFile("bin", null, + null); return new FilterOutputStream(new FileOutputStream(tmpFile)) { @@ -739,27 +772,20 @@ synchronized (updateDataSQL) { long length = tmpFile.length(); in = new FileInputStream(tmpFile); - executeStmt(updateDataSQL, - new Object[]{ - new SizedInputStream(in, length), - new Long(System.currentTimeMillis()), - new Long(length), - parentDir, - name - }); + executeStmt(updateDataSQL, new Object[] { + new SizedInputStream(in, length), + new Long(System.currentTimeMillis()), + new Long(length), parentDir, name}); } } else { synchronized (insertFileSQL) { long length = tmpFile.length(); in = new FileInputStream(tmpFile); - executeStmt(insertFileSQL, - new Object[]{ - parentDir, - name, - new SizedInputStream(in, length), - new Long(System.currentTimeMillis()), - new Long(length) - }); + executeStmt(insertFileSQL, new Object[] { + parentDir, name, + new SizedInputStream(in, length), + new Long(System.currentTimeMillis()), + new Long(length)}); } } @@ -784,8 +810,9 @@ /** * {@inheritDoc} */ - public RandomAccessOutputStream getRandomAccessOutputStream(final String filePath) - throws FileSystemException, UnsupportedOperationException { + public RandomAccessOutputStream getRandomAccessOutputStream( + final String filePath) throws FileSystemException, + UnsupportedOperationException { if (!initialized) { throw new IllegalStateException("not initialized"); } @@ -804,8 +831,10 @@ } try { - TransientFileFactory fileFactory = TransientFileFactory.getInstance(); - final File tmpFile = fileFactory.createTransientFile("bin", null, null); + TransientFileFactory fileFactory = TransientFileFactory + .getInstance(); + final File tmpFile = fileFactory.createTransientFile("bin", null, + null); // @todo FIXME use java.sql.Blob @@ -826,8 +855,8 @@ } return new RandomAccessOutputStream() { - private final RandomAccessFile raf = - new RandomAccessFile(tmpFile, "rw"); + private final RandomAccessFile raf = new RandomAccessFile( + tmpFile, "rw"); public void close() throws IOException { raf.close(); @@ -838,27 +867,20 @@ synchronized (updateDataSQL) { long length = tmpFile.length(); in = new FileInputStream(tmpFile); - executeStmt(updateDataSQL, - new Object[]{ - new SizedInputStream(in, length), - new Long(System.currentTimeMillis()), - new Long(length), - parentDir, - name - }); + executeStmt(updateDataSQL, new Object[] { + new SizedInputStream(in, length), + new Long(System.currentTimeMillis()), + new Long(length), parentDir, name}); } } else { synchronized (insertFileSQL) { long length = tmpFile.length(); in = new FileInputStream(tmpFile); - executeStmt(insertFileSQL, - new Object[]{ - parentDir, - name, - new SizedInputStream(in, length), - new Long(System.currentTimeMillis()), - new Long(length) - }); + executeStmt(insertFileSQL, new Object[] { + parentDir, name, + new SizedInputStream(in, length), + new Long(System.currentTimeMillis()), + new Long(length)}); } } @@ -881,7 +903,7 @@ raf.write(b); } - public void flush() /*throws IOException*/ { + public void flush() /* throws IOException */ { // nop } @@ -889,7 +911,8 @@ raf.write(b); } - public void write(byte[] b, int off, int len) throws IOException { + public void write(byte[] b, int off, int len) + throws IOException { raf.write(b, off, len); } }; @@ -903,7 +926,8 @@ /** * {@inheritDoc} */ - public void copy(String srcPath, String destPath) throws FileSystemException { + public void copy(String srcPath, String destPath) + throws FileSystemException { if (!initialized) { throw new IllegalStateException("not initialized"); } @@ -923,7 +947,8 @@ /** * {@inheritDoc} */ - public void move(String srcPath, String destPath) throws FileSystemException { + public void move(String srcPath, String destPath) + throws FileSystemException { if (!initialized) { throw new IllegalStateException("not initialized"); } @@ -940,17 +965,18 @@ } } - //----------------------------------< misc. helper methods & overridables > + // ----------------------------------< misc. helper methods & overridables > /** * Initializes the database connection used by this file system. *
- * Subclasses should normally override the {@link #getConnection()}
- * method instead of this one. The default implementation calls
- * {@link #getConnection()} to get the database connection and disables
- * the autocommit feature.
+ * Subclasses should normally override the {@link #getConnection()} method
+ * instead of this one. The default implementation calls
+ * {@link #getConnection()} to get the database connection and disables the
+ * autocommit feature.
*
- * @throws Exception if an error occurs
+ * @throws Exception
+ * if an error occurs
*/
protected void initConnection() throws Exception {
con = getConnection();
@@ -961,15 +987,16 @@
* Abstract factory method for creating a new database connection. This
* method is called by {@link #initConnection()} when the file system is
* started. The returned connection should come with the default JDBC
- * settings, as the {@link #initConnection()} method will explicitly set
- * the autoCommit and other properties as needed.
+ * settings, as the {@link #initConnection()} method will explicitly set the
+ * autoCommit and other properties as needed.
*
* Note that the returned database connection is kept during the entire - * lifetime of the file system, after which it is closed by - * {@link #close()} using the {@link #closeConnection(Connection)} method. + * lifetime of the file system, after which it is closed by {@link #close()} + * using the {@link #closeConnection(Connection)} method. * * @return new connection - * @throws Exception if an error occurs + * @throws Exception + * if an error occurs */ protected Connection getConnection() throws Exception { throw new UnsupportedOperationException("Override in a subclass!"); @@ -981,11 +1008,13 @@ * {@link #getConnection()} when the file system was started. *
* The default implementation just calls the {@link Connection#close()}
- * method of the given connection, but subclasses can override this
- * method to provide more extensive database and connection cleanup.
+ * method of the given connection, but subclasses can override this method
+ * to provide more extensive database and connection cleanup.
*
- * @param connection database connection
- * @throws SQLException if an error occurs
+ * @param connection
+ * database connection
+ * @throws SQLException
+ * if an error occurs
*/
protected void closeConnection(Connection connection) throws SQLException {
connection.close();
@@ -1004,7 +1033,8 @@
// gracefully in order to avoid potential memory leaks
// close shared prepared statements
- for (Iterator it = preparedStatements.values().iterator(); it.hasNext(); ) {
+ for (Iterator it = preparedStatements.values().iterator();
+ it.hasNext();) {
closeStatement((PreparedStatement) it.next());
}
preparedStatements.clear();
@@ -1035,20 +1065,24 @@
}
/**
- * Executes the given SQL statement with the specified parameters.
- * If a SQLException is encountered one attempt is made
- * to re-establish the database connection and re-execute the statement.
+ * Executes the given SQL statement with the specified parameters. If a
+ * SQLException is encountered one attempt is made to
+ * re-establish the database connection and re-execute the statement.
*
- * @param sql statement to execute
- * @param params parameters to set
+ * @param sql
+ * statement to execute
+ * @param params
+ * parameters to set
* @return the Statement object that had been executed
- * @throws SQLException if an error occurs
+ * @throws SQLException
+ * if an error occurs
*/
protected Statement executeStmt(String sql, Object[] params)
throws SQLException {
int trials = 2;
while (true) {
- PreparedStatement stmt = (PreparedStatement) preparedStatements.get(sql);
+ PreparedStatement stmt = (PreparedStatement) preparedStatements
+ .get(sql);
try {
for (int i = 0; i < params.length; i++) {
if (params[i] instanceof SizedInputStream) {
@@ -1066,7 +1100,8 @@
// no more trials, re-throw
throw se;
}
- log.warn("execute failed, about to reconnect...", se.getMessage());
+ log.warn("execute failed, about to reconnect...", se
+ .getMessage());
// try to reconnect
if (reestablishConnection()) {
@@ -1100,7 +1135,8 @@
* characters that are allowed in names on the target database. Illegal
* characters will be escaped as necessary.
*
- * @throws Exception if an error occurs
+ * @throws Exception
+ * if an error occurs
*/
protected void prepareSchemaObjectPrefix() throws Exception {
DatabaseMetaData metaData = con.getMetaData();
@@ -1128,7 +1164,8 @@
* Checks if the required schema objects exist and creates them if they
* don't exist yet.
*
- * @throws Exception if an error occurs
+ * @throws Exception
+ * if an error occurs
*/
protected void checkSchema() throws Exception {
DatabaseMetaData metaData = con.getMetaData();
@@ -1150,11 +1187,13 @@
// read ddl from resources
InputStream in = getClass().getResourceAsStream(schema + ".ddl");
if (in == null) {
- String msg = "Configuration error: unknown schema '" + schema + "'";
+ String msg = "Configuration error: unknown schema '" + schema
+ + "'";
log.debug(msg);
throw new RepositoryException(msg);
}
- BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(in));
Statement stmt = con.createStatement();
try {
String sql = reader.readLine();
@@ -1162,7 +1201,8 @@
// Skip comments and empty lines
if (!sql.startsWith("#") && sql.length() > 0) {
// replace prefix variable
- sql = Text.replace(sql, SCHEMA_OBJECT_PREFIX_VARIABLE, schemaObjectPrefix);
+ sql = Text.replace(sql, SCHEMA_OBJECT_PREFIX_VARIABLE,
+ schemaObjectPrefix);
// execute sql stmt
stmt.executeUpdate(sql);
}
@@ -1180,46 +1220,47 @@
* Builds the SQL statements
*/
protected void buildSQLStatements() {
- insertFileSQL = "insert into "
- + schemaObjectPrefix + "FSENTRY "
+ insertFileSQL = "insert into " + schemaObjectPrefix + "FSENTRY "
+ "(FSENTRY_PATH, FSENTRY_NAME, FSENTRY_DATA, "
+ "FSENTRY_LASTMOD, FSENTRY_LENGTH) "
+ "values (?, ?, ?, ?, ?)";
insertFolderSQL = "insert into "
- + schemaObjectPrefix + "FSENTRY "
- + "(FSENTRY_PATH, FSENTRY_NAME, FSENTRY_LASTMOD, FSENTRY_LENGTH) "
- + "values (?, ?, ?, 0)";
+ + schemaObjectPrefix
+ + "FSENTRY "
+ + "(FSENTRY_PATH, FSENTRY_NAME, FSENTRY_LASTMOD, FSENTRY_LENGTH"
+ + ") values (?, ?, ?, 0)";
updateDataSQL = "update "
- + schemaObjectPrefix + "FSENTRY "
- + "set FSENTRY_DATA = ?, FSENTRY_LASTMOD = ?, FSENTRY_LENGTH = ? "
+ + schemaObjectPrefix
+ + "FSENTRY "
+ + "set FSENTRY_DATA = ?, FSENTRY_LASTMOD = ?, "
+ + "FSENTRY_LENGTH = ? "
+ "where FSENTRY_PATH = ? and FSENTRY_NAME = ? "
+ "and FSENTRY_DATA is not null";
- updateLastModifiedSQL = "update "
- + schemaObjectPrefix + "FSENTRY set FSENTRY_LASTMOD = ? "
+ updateLastModifiedSQL = "update " + schemaObjectPrefix
+ + "FSENTRY set FSENTRY_LASTMOD = ? "
+ "where FSENTRY_PATH = ? and FSENTRY_NAME = ? "
+ "and FSENTRY_DATA is not null";
- selectExistSQL = "select 1 from "
- + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
- + "and FSENTRY_NAME = ?";
+ selectExistSQL = "select 1 from " + schemaObjectPrefix
+ + "FSENTRY where FSENTRY_PATH = ? " + "and FSENTRY_NAME = ?";
- selectFileExistSQL = "select 1 from "
- + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+ selectFileExistSQL = "select 1 from " + schemaObjectPrefix
+ + "FSENTRY where FSENTRY_PATH = ? "
+ "and FSENTRY_NAME = ? and FSENTRY_DATA is not null";
- selectFolderExistSQL = "select 1 from "
- + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+ selectFolderExistSQL = "select 1 from " + schemaObjectPrefix
+ + "FSENTRY where FSENTRY_PATH = ? "
+ "and FSENTRY_NAME = ? and FSENTRY_DATA is null";
- selectFileNamesSQL = "select FSENTRY_NAME from "
- + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+ selectFileNamesSQL = "select FSENTRY_NAME from " + schemaObjectPrefix
+ + "FSENTRY where FSENTRY_PATH = ? "
+ "and FSENTRY_DATA is not null";
- selectFolderNamesSQL = "select FSENTRY_NAME from "
- + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+ selectFolderNamesSQL = "select FSENTRY_NAME from " + schemaObjectPrefix
+ + "FSENTRY where FSENTRY_PATH = ? "
+ "and FSENTRY_DATA is null";
selectFileAndFolderNamesSQL = "select FSENTRY_NAME from "
@@ -1228,89 +1269,88 @@
selectChildCountSQL = "select count(FSENTRY_NAME) from "
+ schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? ";
- selectDataSQL = "select FSENTRY_DATA from "
- + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+ selectDataSQL = "select FSENTRY_DATA from " + schemaObjectPrefix
+ + "FSENTRY where FSENTRY_PATH = ? "
+ "and FSENTRY_NAME = ? and FSENTRY_DATA is not null";
selectLastModifiedSQL = "select FSENTRY_LASTMOD from "
+ schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+ "and FSENTRY_NAME = ?";
- selectLengthSQL = "select FSENTRY_LENGTH from "
- + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+ selectLengthSQL = "select FSENTRY_LENGTH from " + schemaObjectPrefix
+ + "FSENTRY where FSENTRY_PATH = ? "
+ "and FSENTRY_NAME = ? and FSENTRY_DATA is not null";
- deleteFileSQL = "delete from "
- + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+ deleteFileSQL = "delete from " + schemaObjectPrefix
+ + "FSENTRY where FSENTRY_PATH = ? "
+ "and FSENTRY_NAME = ? and FSENTRY_DATA is not null";
deleteFolderSQL = "delete from "
- + schemaObjectPrefix + "FSENTRY where "
- + "(FSENTRY_PATH = ? and FSENTRY_NAME = ? and FSENTRY_DATA is null) "
- + "or (FSENTRY_PATH = ?) "
- + "or (FSENTRY_PATH like ?) ";
+ + schemaObjectPrefix
+ + "FSENTRY where "
+ + "(FSENTRY_PATH = ? and FSENTRY_NAME = ? "
+ + "and FSENTRY_DATA is null) "
+ + "or (FSENTRY_PATH = ?) " + "or (FSENTRY_PATH like ?) ";
- copyFileSQL = "insert into "
- + schemaObjectPrefix + "FSENTRY "
+ copyFileSQL = "insert into " + schemaObjectPrefix + "FSENTRY "
+ "(FSENTRY_PATH, FSENTRY_NAME, FSENTRY_DATA, "
+ "FSENTRY_LASTMOD, FSENTRY_LENGTH) "
+ "select ?, ?, FSENTRY_DATA, "
- + "FSENTRY_LASTMOD, FSENTRY_LENGTH from "
- + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+ + "FSENTRY_LASTMOD, FSENTRY_LENGTH from " + schemaObjectPrefix
+ + "FSENTRY where FSENTRY_PATH = ? "
+ "and FSENTRY_NAME = ? and FSENTRY_DATA is not null";
- copyFilesSQL = "insert into "
- + schemaObjectPrefix + "FSENTRY "
+ copyFilesSQL = "insert into " + schemaObjectPrefix + "FSENTRY "
+ "(FSENTRY_PATH, FSENTRY_NAME, FSENTRY_DATA, "
+ "FSENTRY_LASTMOD, FSENTRY_LENGTH) "
+ "select ?, FSENTRY_NAME, FSENTRY_DATA, "
- + "FSENTRY_LASTMOD, FSENTRY_LENGTH from "
- + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+ + "FSENTRY_LASTMOD, FSENTRY_LENGTH from " + schemaObjectPrefix
+ + "FSENTRY where FSENTRY_PATH = ? "
+ "and FSENTRY_DATA is not null";
}
/**
* Initializes the map of prepared statements.
*
- * @throws SQLException if an error occurs
+ * @throws SQLException
+ * if an error occurs
*/
protected void initPreparedStatements() throws SQLException {
- preparedStatements.put(
- selectExistSQL, con.prepareStatement(selectExistSQL));
- preparedStatements.put(
- selectFileExistSQL, con.prepareStatement(selectFileExistSQL));
- preparedStatements.put(
- selectFolderExistSQL, con.prepareStatement(selectFolderExistSQL));
- preparedStatements.put(
- selectChildCountSQL, con.prepareStatement(selectChildCountSQL));
- preparedStatements.put(
- selectDataSQL, con.prepareStatement(selectDataSQL));
- preparedStatements.put(
- selectLastModifiedSQL, con.prepareStatement(selectLastModifiedSQL));
- preparedStatements.put(
- selectLengthSQL, con.prepareStatement(selectLengthSQL));
- preparedStatements.put(
- selectFileNamesSQL, con.prepareStatement(selectFileNamesSQL));
- preparedStatements.put(
- selectFolderNamesSQL, con.prepareStatement(selectFolderNamesSQL));
- preparedStatements.put(
- selectFileAndFolderNamesSQL, con.prepareStatement(selectFileAndFolderNamesSQL));
- preparedStatements.put(
- deleteFileSQL, con.prepareStatement(deleteFileSQL));
- preparedStatements.put(
- deleteFolderSQL, con.prepareStatement(deleteFolderSQL));
- preparedStatements.put(
- insertFileSQL, con.prepareStatement(insertFileSQL));
- preparedStatements.put(
- insertFolderSQL, con.prepareStatement(insertFolderSQL));
- preparedStatements.put(
- updateDataSQL, con.prepareStatement(updateDataSQL));
- preparedStatements.put(
- updateLastModifiedSQL, con.prepareStatement(updateLastModifiedSQL));
- preparedStatements.put(
- copyFileSQL, con.prepareStatement(copyFileSQL));
- preparedStatements.put(
- copyFilesSQL, con.prepareStatement(copyFilesSQL));
+ preparedStatements.put(selectExistSQL, con
+ .prepareStatement(selectExistSQL));
+ preparedStatements.put(selectFileExistSQL, con
+ .prepareStatement(selectFileExistSQL));
+ preparedStatements.put(selectFolderExistSQL, con
+ .prepareStatement(selectFolderExistSQL));
+ preparedStatements.put(selectChildCountSQL, con
+ .prepareStatement(selectChildCountSQL));
+ preparedStatements.put(selectDataSQL, con
+ .prepareStatement(selectDataSQL));
+ preparedStatements.put(selectLastModifiedSQL, con
+ .prepareStatement(selectLastModifiedSQL));
+ preparedStatements.put(selectLengthSQL, con
+ .prepareStatement(selectLengthSQL));
+ preparedStatements.put(selectFileNamesSQL, con
+ .prepareStatement(selectFileNamesSQL));
+ preparedStatements.put(selectFolderNamesSQL, con
+ .prepareStatement(selectFolderNamesSQL));
+ preparedStatements.put(selectFileAndFolderNamesSQL, con
+ .prepareStatement(selectFileAndFolderNamesSQL));
+ preparedStatements.put(deleteFileSQL, con
+ .prepareStatement(deleteFileSQL));
+ preparedStatements.put(deleteFolderSQL, con
+ .prepareStatement(deleteFolderSQL));
+ preparedStatements.put(insertFileSQL, con
+ .prepareStatement(insertFileSQL));
+ preparedStatements.put(insertFolderSQL, con
+ .prepareStatement(insertFolderSQL));
+ preparedStatements.put(updateDataSQL, con
+ .prepareStatement(updateDataSQL));
+ preparedStatements.put(updateLastModifiedSQL, con
+ .prepareStatement(updateLastModifiedSQL));
+ preparedStatements.put(copyFileSQL, con.prepareStatement(copyFileSQL));
+ preparedStatements
+ .put(copyFilesSQL, con.prepareStatement(copyFilesSQL));
}
@@ -1318,16 +1358,16 @@
* Verifies that the root file system entry exists. If it doesn't exist yet
* it will be automatically created.
*
- * @throws Exception if an error occurs
+ * @throws Exception
+ * if an error occurs
*/
protected void verifyRootExists() throws Exception {
// check if root file system entry exists
synchronized (selectFolderExistSQL) {
ResultSet rs = null;
try {
- Statement stmt = executeStmt(
- selectFolderExistSQL,
- new Object[]{FileSystem.SEPARATOR, ""});
+ Statement stmt = executeStmt(selectFolderExistSQL,
+ new Object[] {FileSystem.SEPARATOR, ""});
rs = stmt.getResultSet();
if (rs.next()) {
@@ -1335,7 +1375,8 @@
return;
}
} catch (SQLException e) {
- String msg = "failed to check existence of file system root entry";
+ String msg = "failed to check existence of file system root "
+ + "entry";
log.error(msg, e);
throw new FileSystemException(msg, e);
} finally {
@@ -1348,11 +1389,13 @@
}
/**
- * Creates the specified files system folder entry, recursively creating
- * any non-existing intermediate folder entries.
+ * Creates the specified files system folder entry, recursively creating any
+ * non-existing intermediate folder entries.
*
- * @param folderPath folder entry to create
- * @throws FileSystemException if an error occurs
+ * @param folderPath
+ * folder entry to create
+ * @throws FileSystemException
+ * if an error occurs
*/
protected void createDeepFolder(String folderPath)
throws FileSystemException {
@@ -1367,12 +1410,8 @@
synchronized (insertFolderSQL) {
try {
- executeStmt(
- insertFolderSQL,
- new Object[]{
- parentDir,
- name,
- new Long(System.currentTimeMillis())});
+ executeStmt(insertFolderSQL, new Object[] {parentDir, name,
+ new Long(System.currentTimeMillis())});
} catch (SQLException e) {
String msg = "failed to create folder entry: " + folderPath;
log.error(msg, e);
@@ -1384,9 +1423,12 @@
/**
* Recursively copies the given folder to the given destination.
*
- * @param srcPath folder to be copied
- * @param destPath destination path to which the folder is to be copied
- * @throws FileSystemException if an error occurs
+ * @param srcPath
+ * folder to be copied
+ * @param destPath
+ * destination path to which the folder is to be copied
+ * @throws FileSystemException
+ * if an error occurs
*/
protected void copyDeepFolder(String srcPath, String destPath)
throws FileSystemException {
@@ -1398,18 +1440,19 @@
String[] names = listFolders(srcPath);
for (int i = 0; i < names.length; i++) {
- String src = (FileSystemPathUtil.denotesRoot(srcPath)
- ? srcPath + names[i] : srcPath + FileSystem.SEPARATOR + names[i]);
- String dest = (FileSystemPathUtil.denotesRoot(destPath)
- ? destPath + names[i] : destPath + FileSystem.SEPARATOR + names[i]);
+ String src = (FileSystemPathUtil.denotesRoot(srcPath) ? srcPath
+ + names[i] : srcPath + FileSystem.SEPARATOR + names[i]);
+ String dest = (FileSystemPathUtil.denotesRoot(destPath) ? destPath
+ + names[i] : destPath + FileSystem.SEPARATOR + names[i]);
copyDeepFolder(src, dest);
}
synchronized (copyFilesSQL) {
try {
- executeStmt(copyFilesSQL, new Object[]{destPath, srcPath});
+ executeStmt(copyFilesSQL, new Object[] {destPath, srcPath});
} catch (SQLException e) {
- String msg = "failed to copy file entries from " + srcPath + " to " + destPath;
+ String msg = "failed to copy file entries from " + srcPath
+ + " to " + destPath;
log.error(msg, e);
throw new FileSystemException(msg, e);
}
@@ -1422,9 +1465,12 @@
* already. If the destination path refers to an existing file, the file
* will be overwritten.
*
- * @param srcPath file to be copied
- * @param destPath destination path to which the file is to be copied
- * @throws FileSystemException if an error occurs
+ * @param srcPath
+ * file to be copied
+ * @param destPath
+ * destination path to which the file is to be copied
+ * @throws FileSystemException
+ * if an error occurs
*/
protected void copyFile(String srcPath, String destPath)
throws FileSystemException {
@@ -1445,16 +1491,12 @@
int count = 0;
synchronized (copyFileSQL) {
try {
- Statement stmt = executeStmt(
- copyFileSQL,
- new Object[]{
- destParentDir,
- destName,
- srcParentDir,
- srcName});
+ Statement stmt = executeStmt(copyFileSQL, new Object[] {
+ destParentDir, destName, srcParentDir, srcName});
count = stmt.getUpdateCount();
} catch (SQLException e) {
- String msg = "failed to copy file from " + srcPath + " to " + destPath;
+ String msg = "failed to copy file from " + srcPath + " to "
+ + destPath;
log.error(msg, e);
throw new FileSystemException(msg, e);
}
@@ -1466,15 +1508,15 @@
}
/**
- * Resets the given PreparedStatement by clearing the parameters
- * and warnings contained.
- *
PreparedStatement instance on which it
- * operates are thread safe.
+ * Resets the given PreparedStatement by clearing the
+ * parameters and warnings contained. NOTE: This method MUST be called
+ * in a synchronized context as neither this method nor the
+ * PreparedStatement instance on which it operates are thread
+ * safe.
*
- * @param stmt The PreparedStatement to reset. If
- * null this method does nothing.
+ * @param stmt
+ * The PreparedStatement to reset. If
+ * null this method does nothing.
*/
protected void resetStatement(PreparedStatement stmt) {
if (stmt != null) {
@@ -1517,10 +1559,11 @@
}
}
- //--------------------------------------------------------< inner classes >
+ // --------------------------------------------------------< inner classes >
class SizedInputStream extends FilterInputStream {
private final long size;
+
private boolean consumed = false;
SizedInputStream(InputStream in, long size) {
@@ -1546,12 +1589,12 @@
return super.skip(n);
}
- public int read(byte b[]) throws IOException {
+ public int read(byte[] b) throws IOException {
consumed = true;
return super.read(b);
}
- public int read(byte b[], int off, int len) throws IOException {
+ public int read(byte[] b, int off, int len) throws IOException {
consumed = true;
return super.read(b, off, len);
}
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/DB2FileSystem.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/DB2FileSystem.java (revision 483490)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/DB2FileSystem.java (working copy)
@@ -18,29 +18,30 @@
/**
* DB2FileSystem is a JDBC-based FileSystem
- * implementation for Jackrabbit that persists file system entries in a
- * DB2 database.
- *
- * It is configured through the following properties:
+ * implementation for Jackrabbit that persists file system entries in a DB2
+ * database. It is configured through the following properties:
* driver: the FQN name of the JDBC driver class
- * (default: "com.ibm.db2.jcc.DB2Driver")schema: type of schema to be used
- * (default: "db2")driver: the FQN name of the JDBC driver class (default:
+ * "com.ibm.db2.jcc.DB2Driver")schema: type of schema to be used (default:
+ * "db2")url: the database url (e.g.
* "jdbc:db2:[database]")user: the database userpassword: the user's passwordschemaObjectPrefix: prefix to be prepended to schema objectsschemaObjectPrefix: prefix to be prepended to schema
+ * objects- * <FileSystem class="org.apache.jackrabbit.core.fs.db.DB2FileSystem"> - * <param name="url" value="jdbc:db2:test"/> - * <param name="schemaObjectPrefix" value="rep_"/> - * </FileSystem> + * <FileSystem + * class="org.apache.jackrabbit.core.fs.db.DB2FileSystem"> + * <param name="url" value="jdbc:db2:test"/> + * <param name="schemaObjectPrefix" + * value="rep_"/> + * </FileSystem> **/ public class DB2FileSystem extends DbFileSystem { @@ -58,33 +59,34 @@ initialized = false; } - //-----------------------------------------< DatabaseFileSystem overrides > + // -----------------------------------------< DatabaseFileSystem overrides > /** - * {@inheritDoc} - * - * Since DB2 requires parameter markers within the select clause to be - * explicitly typed using
cast(? as type_name) some statements
- * had to be changed accordingly.
+ * {@inheritDoc} Since DB2 requires parameter markers within the select
+ * clause to be explicitly typed using cast(? as type_name)
+ * some statements had to be changed accordingly.
*/
protected void buildSQLStatements() {
super.buildSQLStatements();
copyFileSQL = "insert into "
- + schemaObjectPrefix + "FSENTRY "
+ + schemaObjectPrefix
+ + "FSENTRY "
+ "(FSENTRY_PATH, FSENTRY_NAME, FSENTRY_DATA, "
+ "FSENTRY_LASTMOD, FSENTRY_LENGTH) "
- + "select cast(? as varchar(745)), cast(? as varchar(255)), FSENTRY_DATA, "
- + "FSENTRY_LASTMOD, FSENTRY_LENGTH from "
- + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+ + "select cast(? as varchar(745)), cast(? as varchar(255)), "
+ + "FSENTRY_DATA, FSENTRY_LASTMOD, FSENTRY_LENGTH from "
+ + schemaObjectPrefix
+ + "FSENTRY where FSENTRY_PATH = ? "
+ "and FSENTRY_NAME = ? and FSENTRY_DATA is not null";
copyFilesSQL = "insert into "
- + schemaObjectPrefix + "FSENTRY "
+ + schemaObjectPrefix
+ + "FSENTRY "
+ "(FSENTRY_PATH, FSENTRY_NAME, FSENTRY_DATA, "
+ "FSENTRY_LASTMOD, FSENTRY_LENGTH) "
+ "select cast(? as varchar(745)), FSENTRY_NAME, FSENTRY_DATA, "
- + "FSENTRY_LASTMOD, FSENTRY_LENGTH from "
- + schemaObjectPrefix + "FSENTRY where FSENTRY_PATH = ? "
+ + "FSENTRY_LASTMOD, FSENTRY_LENGTH from " + schemaObjectPrefix
+ + "FSENTRY where FSENTRY_PATH = ? "
+ "and FSENTRY_DATA is not null";
}
}
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/DbFileSystem.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/DbFileSystem.java (revision 483490)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/DbFileSystem.java (working copy)
@@ -22,70 +22,96 @@
/**
* DbFileSystem is a generic JDBC-based FileSystem
- * implementation for Jackrabbit that persists file system entries in a
- * database table.
- *
- * It is configured through the following properties:
+ * implementation for Jackrabbit that persists file system entries in a database
+ * table. It is configured through the following properties:
* driver: the FQN name of the JDBC driver classurl: the database url of the form jdbc:subprotocol:subnameurl: the database url of the form
+ * jdbc:subprotocol:subnameuser: the database userpassword: the user's passwordschema: type of schema to be used
- * (e.g. mysql, mssql, etc.); schemaObjectPrefix: prefix to be prepended to schema objectsschema: type of schema to be used (e.g.
+ * mysql, mssql, etc.); schemaObjectPrefix: prefix to be prepended to schema
+ * objectsgetClass().getResourceAsStream(schema + ".ddl").
- * Every line in the specified .ddl file is executed separatly by calling
- * java.sql.Statement.execute(String) where every occurence of the
- * the string "${schemaObjectPrefix}" has been replaced with the
- * value of the property schemaObjectPrefix.
- *
- * The following is a fragment from a sample configuration using MySQL:
+ * resources by calling
+ * getClass().getResourceAsStream(schema + ".ddl"). Every line
+ * in the specified .ddl file is executed separatly by calling
+ * java.sql.Statement.execute(String) where every occurence of
+ * the the string "${schemaObjectPrefix}" has been replaced with
+ * the value of the property schemaObjectPrefix. The
+ * following is a fragment from a sample configuration using MySQL:
+ *
* - * <FileSystem class="org.apache.jackrabbit.core.fs.db.DbFileSystem"> - * <param name="driver" value="com.mysql.jdbc.Driver"/> - * <param name="url" value="jdbc:mysql:///test?autoReconnect=true"/> - * <param name="schema" value="mysql"/> - * <param name="schemaObjectPrefix" value="rep_"/> - * </FileSystem> + * <FileSystem + * class="org.apache.jackrabbit.core.fs.db.DbFileSystem"> + * <param name="driver" + * value="com.mysql.jdbc.Driver"/> + * <param name="url" + * value="jdbc:mysql:///test?autoReconnect=true"/> + * <param name="schema" value="mysql"/> + * <param name="schemaObjectPrefix" + * value="rep_"/> + * </FileSystem> *- * The following is a fragment from a sample configuration using Daffodil One$DB Embedded: + * + * The following is a fragment from a sample configuration using Daffodil One$DB + * Embedded: + * *
- * <FileSystem class="org.apache.jackrabbit.core.fs.db.DbFileSystem">
- * <param name="driver" value="in.co.daffodil.db.jdbc.DaffodilDBDriver"/>
- * <param name="url" value="jdbc:daffodilDB_embedded:rep;path=${rep.home}/databases;create=true"/>
- * <param name="user" value="daffodil"/>
- * <param name="password" value="daffodil"/>
- * <param name="schema" value="daffodil"/>
- * <param name="schemaObjectPrefix" value="rep_"/>
- * </FileSystem>
+ * <FileSystem
+ * class="org.apache.jackrabbit.core.fs.db.DbFileSystem">
+ * <param name="driver"
+ * value="in.co.daffodil.db.jdbc.DaffodilDBDriver"/>
+ * <param name="url"
+ * value="jdbc:daffodilDB_embedded:rep;path=${rep.home}/databases;create=true"/>
+ * <param name="user" value="daffodil"/>
+ * <param name="password" value="daffodil"/>
+ * <param name="schema" value="daffodil"/>
+ * <param name="schemaObjectPrefix"
+ * value="rep_"/>
+ * </FileSystem>
*
+ *
* The following is a fragment from a sample configuration using MSSQL:
+ *
* - * <FileSystem class="org.apache.jackrabbit.core.fs.db.DbFileSystem"> - * <param name="driver" value="com.microsoft.jdbc.sqlserver.SQLServerDriver"/> - * <param name="url" value="jdbc:microsoft:sqlserver://localhost:1433;;DatabaseName=test;SelectMethod=Cursor;"/> - * <param name="schema" value="mssql"/> - * <param name="user" value="sa"/> - * <param name="password" value=""/> - * <param name="schemaObjectPrefix" value="rep_"/> - * </FileSystem> + * <FileSystem + * class="org.apache.jackrabbit.core.fs.db.DbFileSystem"> + * <param name="driver" + * value="com.microsoft.jdbc.sqlserver.SQLServerDriver"/> + * <param name="url" + * value="jdbc:microsoft:sqlserver://localhost:1433;;DatabaseName=test;SelectMethod=Cursor;"/> + * <param name="schema" value="mssql"/> + * <param name="user" value="sa"/> + * <param name="password" value=""/> + * <param name="schemaObjectPrefix" + * value="rep_"/> + * </FileSystem> *+ * * The following is a fragment from a sample configuration using PostgreSQL: + * *
- * <FileSystem class="org.apache.jackrabbit.core.fs.db.DbFileSystem"> - * <param name="driver" value="org.postgresql.Driver"/> - * <param name="url" value="jdbc:postgresql://localhost/test"/> - * <param name="schema" value="postgresql"/> - * <param name="user" value="postgres"/> - * <param name="password" value="postgres"/> - * <param name="schemaObjectPrefix" value="rep_"/> - * </FileSystem> + * <FileSystem + * class="org.apache.jackrabbit.core.fs.db.DbFileSystem"> + * <param name="driver" + * value="org.postgresql.Driver"/> + * <param name="url" + * value="jdbc:postgresql://localhost/test"/> + * <param name="schema" value="postgresql"/> + * <param name="user" value="postgres"/> + * <param name="password" value="postgres"/> + * <param name="schemaObjectPrefix" + * value="rep_"/> + * </FileSystem> *- * See also {@link DerbyFileSystem}, {@link DB2FileSystem}, {@link OracleFileSystem}. + * + * See also {@link DerbyFileSystem}, {@link DB2FileSystem}, + * {@link OracleFileSystem}. */ public class DbFileSystem extends DatabaseFileSystem { @@ -109,7 +135,7 @@ */ protected String password; - //----------------------------------------------------< setters & getters > + // ----------------------------------------------------< setters & getters > public String getUrl() { return url; } @@ -142,8 +168,7 @@ this.driver = driver; } - - //-------------------------------------------< java.lang.Object overrides > + // -------------------------------------------< java.lang.Object overrides > /** * {@inheritDoc} */ @@ -153,11 +178,14 @@ } if (obj instanceof DbFileSystem) { DbFileSystem other = (DbFileSystem) obj; - if (((driver != null) ? driver.equals(other.driver) : other.driver == null) - && ((url != null) ? url.equals(other.url) : other.url == null) - && ((user != null) ? user.equals(other.user) : other.user == null) - && ((password != null) ? password.equals(other.password) : other.password == null) - && super.equals(other)) { + if (((driver != null) ? driver.equals(other.driver) + : other.driver == null) + && ((url != null) ? url.equals(other.url) + : other.url == null) + && ((user != null) ? user.equals(other.user) + : other.user == null) + && ((password != null) ? password.equals(other.password) + : other.password == null) && super.equals(other)) { return true; } } @@ -165,8 +193,8 @@ } /** - * Returns zero to satisfy the Object equals/hashCode contract. - * This class is mutable and not meant to be used as a hash key. + * Returns zero to satisfy the Object equals/hashCode contract. This class + * is mutable and not meant to be used as a hash key. * * @return always zero * @see Object#hashCode() @@ -175,14 +203,16 @@ return 0; } - //--------------------------------------------------< DatabaseFileSystem > + // --------------------------------------------------< DatabaseFileSystem > /** * Initialize the JDBC connection. * - * @throws SQLException if an error occurs + * @throws SQLException + * if an error occurs */ - protected Connection getConnection() throws ClassNotFoundException, SQLException { + protected Connection getConnection() throws ClassNotFoundException, + SQLException { Class.forName(driver); return DriverManager.getConnection(url, user, password); } Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/DerbyFileSystem.java =================================================================== --- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/DerbyFileSystem.java (revision 483490) +++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/DerbyFileSystem.java (working copy) @@ -16,41 +16,45 @@ */ package org.apache.jackrabbit.core.fs.db; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.sql.Connection; - /** *
DerbyFileSystem is a JDBC-based FileSystem
* implementation for Jackrabbit that persists file system entries in an
- * embedded Derby database.
- *
- * It is configured through the following properties:
+ * embedded Derby database. It is configured through the following
+ * properties:
* url: the database url of the form
* "jdbc:derby:[db];[attributes]"schemaObjectPrefix: prefix to be prepended to schema objectsdriver: the FQN name of the JDBC driver class
- * (default: "org.apache.derby.jdbc.EmbeddedDriver")schema: type of schema to be used
- * (default: "derby")schemaObjectPrefix: prefix to be prepended to schema
+ * objectsdriver: the FQN name of the JDBC driver class (default:
+ * "org.apache.derby.jdbc.EmbeddedDriver")schema: type of schema to be used (default:
+ * "derby")user: the database user (default: null)password: the user's password (default: null)shutdownOnClose: if true (the default) the
- * database is shutdown when the last connection is closed;
- * set this to false when using a standalone databasepassword: the user's password (default:
+ * null)shutdownOnClose: if true (the default)
+ * the database is shutdown when the last connection is closed; set this to
+ * false when using a standalone database
- * <FileSystem class="org.apache.jackrabbit.core.fs.db.DerbyFileSystem">
- * <param name="url" value="jdbc:derby:${rep.home}/db;create=true"/>
- * <param name="schemaObjectPrefix" value="rep_"/>
- * </FileSystem>
+ * <FileSystem
+ * class="org.apache.jackrabbit.core.fs.db.DerbyFileSystem">
+ * <param name="url"
+ * value="jdbc:derby:${rep.home}/db;create=true"/>
+ * <param name="schemaObjectPrefix"
+ * value="rep_"/>
+ * </FileSystem>
*
*/
public class DerbyFileSystem extends DbFileSystem {
@@ -76,7 +80,7 @@
initialized = false;
}
- //----------------------------------------------------< setters & getters >
+ // ----------------------------------------------------< setters & getters >
public boolean getShutdownOnClose() {
return shutdownOnClose;
@@ -86,14 +90,16 @@
this.shutdownOnClose = shutdownOnClose;
}
- //-----------------------------------------------< DbFileSystem overrides >
+ // -----------------------------------------------< DbFileSystem overrides >
/**
- * Closes the given connection and shuts down the embedded Derby
- * database if shutdownOnClose is set to true.
+ * Closes the given connection and shuts down the embedded Derby database if
+ * shutdownOnClose is set to true.
*
- * @param connection database connection
- * @throws SQLException if an error occurs
+ * @param connection
+ * database connection
+ * @throws SQLException
+ * if an error occurs
* @see DatabaseFileSystem#closeConnection(Connection)
*/
protected void closeConnection(Connection connection) throws SQLException {
@@ -106,8 +112,10 @@
}
url += ";shutdown=true";
- // we have to reset the connection to 'autoCommit=true' before closing it;
- // otherwise Derby would mysteriously complain about some pending uncommitted
+ // we have to reset the connection to 'autoCommit=true' before closing
+ // it;
+ // otherwise Derby would mysteriously complain about some pending
+ // uncommitted
// changes which can't possibly be true.
// @todo further investigate
connection.setAutoCommit(true);
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/JNDIDatabaseFileSystem.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/JNDIDatabaseFileSystem.java (revision 483490)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/JNDIDatabaseFileSystem.java (working copy)
@@ -16,21 +16,22 @@
*/
package org.apache.jackrabbit.core.fs.db;
+import java.sql.Connection;
+import java.sql.SQLException;
+
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
-import java.sql.Connection;
-import java.sql.SQLException;
/**
- * Database file system that uses JNDI to acquire the database connection.
- * The JNDI location of the {@link DataSource} to be used in given as
- * the dataSourceLocation configuration property. See the
+ * Database file system that uses JNDI to acquire the database connection. The
+ * JNDI location of the {@link DataSource} to be used in given as the
+ * dataSourceLocation configuration property. See the
* {@link DbFileSystem} for more configuration details.
*
- * WARNING: The acquired database connection is kept
- * for the entire lifetime of the file system instance. The configured data
- * source should be prepared for this.
+ * WARNING: The acquired database connection is kept for the
+ * entire lifetime of the file system instance. The configured data source
+ * should be prepared for this.
*/
public class JNDIDatabaseFileSystem extends DatabaseFileSystem {
@@ -39,7 +40,7 @@
*/
private String dataSourceLocation;
- //----------------------------------------------------< setters & getters >
+ // ----------------------------------------------------< setters & getters >
/**
* Returns the JNDI location of the data source.
@@ -53,26 +54,28 @@
/**
* Sets the JNDI location of the data source.
*
- * @param dataSourceLocation data source location
+ * @param dataSourceLocation
+ * data source location
*/
public void setDataSourceLocation(String dataSourceLocation) {
this.dataSourceLocation = dataSourceLocation;
}
- //--------------------------------------------------< DatabaseFileSystem >
+ // --------------------------------------------------< DatabaseFileSystem >
/**
* Returns a JDBC connection from a {@link DataSource} acquired from JNDI
* with the configured data source location.
*
* @return new database connection
- * @throws NamingException if the given data source location does not exist
- * @throws SQLException if a database access error occurs
+ * @throws NamingException
+ * if the given data source location does not exist
+ * @throws SQLException
+ * if a database access error occurs
*/
protected Connection getConnection() throws NamingException, SQLException {
InitialContext ic = new InitialContext();
DataSource dataSource = (DataSource) ic.lookup(dataSourceLocation);
return dataSource.getConnection();
}
-
}
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/OracleFileSystem.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/OracleFileSystem.java (revision 483490)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/fs/db/OracleFileSystem.java (working copy)
@@ -16,59 +16,64 @@
*/
package org.apache.jackrabbit.core.fs.db;
-import org.apache.jackrabbit.util.Text;
-import org.apache.jackrabbit.util.TransientFileFactory;
-import org.apache.jackrabbit.core.fs.FileSystemException;
-import org.apache.jackrabbit.core.fs.FileSystemPathUtil;
-import org.apache.jackrabbit.core.fs.RandomAccessOutputStream;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.jcr.RepositoryException;
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
-import java.sql.Statement;
-import java.sql.Blob;
-import java.sql.Connection;
-import java.io.InputStream;
import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.IOException;
import java.io.File;
-import java.io.FilterOutputStream;
-import java.io.FileOutputStream;
import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.lang.reflect.Method;
+import java.sql.Blob;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.core.fs.FileSystemException;
+import org.apache.jackrabbit.core.fs.FileSystemPathUtil;
+import org.apache.jackrabbit.core.fs.RandomAccessOutputStream;
+import org.apache.jackrabbit.util.Text;
+import org.apache.jackrabbit.util.TransientFileFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* OracleFileSystem is a JDBC-based FileSystem
- * implementation for Jackrabbit that persists file system entries in an
- * Oracle database.
- *
driver: the FQN name of the JDBC driver class
- * (default: "oracle.jdbc.OracleDriver")schema: type of schema to be used
- * (default: "oracle")driver: the FQN name of the JDBC driver class (default:
+ * "oracle.jdbc.OracleDriver")schema: type of schema to be used (default:
+ * "oracle")url: the database url (e.g.
* "jdbc:oracle:thin:@[host]:[port]:[sid]")user: the database userpassword: the user's passwordschemaObjectPrefix: prefix to be prepended to schema objectsschemaObjectPrefix: prefix to be prepended to schema
+ * objects- * <FileSystem class="org.apache.jackrabbit.core.fs.db.OracleFileSystem"> - * <param name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/> - * <param name="user" value="scott"/> - * <param name="password" value="tiger"/> - * <param name="schemaObjectPrefix" value="rep_"/> - * </FileSystem> + * <FileSystem + * class="org.apache.jackrabbit.core.fs.db.OracleFileSystem"> + * <param name="url" + * value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/> + * <param name="user" + * value="scott"/> + * <param name="password" + * value="tiger"/> + * <param name="schemaObjectPrefix" + * value="rep_"/> + * </FileSystem> **/ public class OracleFileSystem extends DbFileSystem { @@ -79,9 +84,11 @@ private static Logger log = LoggerFactory.getLogger(OracleFileSystem.class); private Class blobClass; - private Integer DURATION_SESSION_CONSTANT; - private Integer MODE_READWRITE_CONSTANT; + private Integer durationSessionConstant; + + private Integer modeReadwriteConstant; + /** * Creates a new
OracleFileSystem instance.
*/
@@ -95,13 +102,13 @@
initialized = false;
}
- //-----------------------------------------< DatabaseFileSystem overrides >
+ // -----------------------------------------< DatabaseFileSystem overrides >
/**
- * {@inheritDoc}
- *
- * Retrieve the oracle.sql.BLOB class via reflection, and
- * initialize the values for the DURATION_SESSION and
- * MODE_READWRITE constants defined there.
+ * {@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
*/
@@ -113,11 +120,12 @@
// use the Connection object for using the exact same
// class loader that the Oracle driver was loaded with
try {
- blobClass = con.getClass().getClassLoader().loadClass("oracle.sql.BLOB");
- DURATION_SESSION_CONSTANT =
- new Integer(blobClass.getField("DURATION_SESSION").getInt(null));
- MODE_READWRITE_CONSTANT =
- new Integer(blobClass.getField("MODE_READWRITE").getInt(null));
+ 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));
} catch (Exception e) {
String msg = "failed to load/introspect oracle.sql.BLOB";
log.error(msg, e);
@@ -126,13 +134,12 @@
}
/**
- * {@inheritDoc}
- *
- * Overridden in order to support multiple oracle schemas. Note that
- * schema names in Oracle correspond to the username of the connection.
- * See http://issues.apache.org/jira/browse/JCR-582
+ * {@inheritDoc} Overridden in order to support multiple oracle
+ * schemas. Note that schema names in Oracle correspond to the username of
+ * the connection. See http://issues.apache.org/jira/browse/JCR-582
*
- * @throws Exception if an error occurs
+ * @throws Exception
+ * if an error occurs
*/
protected void checkSchema() throws Exception {
DatabaseMetaData metaData = con.getMetaData();
@@ -156,11 +163,13 @@
// read ddl from resources
InputStream in = getClass().getResourceAsStream(schema + ".ddl");
if (in == null) {
- String msg = "Configuration error: unknown schema '" + schema + "'";
+ String msg = "Configuration error: unknown schema '" + schema
+ + "'";
log.debug(msg);
throw new RepositoryException(msg);
}
- BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(in));
Statement stmt = con.createStatement();
try {
String sql = reader.readLine();
@@ -168,7 +177,8 @@
// Skip comments and empty lines
if (!sql.startsWith("#") && sql.length() > 0) {
// replace prefix variable
- sql = Text.replace(sql, SCHEMA_OBJECT_PREFIX_VARIABLE, schemaObjectPrefix);
+ sql = Text.replace(sql, SCHEMA_OBJECT_PREFIX_VARIABLE,
+ schemaObjectPrefix);
// execute sql stmt
stmt.executeUpdate(sql);
}
@@ -183,11 +193,9 @@
}
/**
- * Builds the SQL statements
- *
- * Since Oracle treats emtpy strings and BLOBs as null values the SQL
- * statements had to be adapated accordingly. The following changes were
- * necessary:
+ * Builds the SQL statements Since Oracle treats emtpy strings and
+ * BLOBs as null values the SQL statements had to be adapated accordingly.
+ * The following changes were necessary:
* oracle.sql.BLOB
- * and PreparedStatement#setBlob instead of just
- * PreparedStatement#setBinaryStream.
+ * {@inheritDoc} Overridden because we need to use
+ * oracle.sql.BLOB and PreparedStatement#setBlob
+ * instead of just PreparedStatement#setBinaryStream.
*/
- public OutputStream getOutputStream(final String filePath) throws FileSystemException {
+ public OutputStream getOutputStream(final String filePath)
+ throws FileSystemException {
if (!initialized) {
throw new IllegalStateException("not initialized");
}
@@ -318,8 +325,10 @@
}
try {
- TransientFileFactory fileFactory = TransientFileFactory.getInstance();
- final File tmpFile = fileFactory.createTransientFile("bin", null, null);
+ TransientFileFactory fileFactory = TransientFileFactory
+ .getInstance();
+ final File tmpFile = fileFactory.createTransientFile("bin", null,
+ null);
return new FilterOutputStream(new FileOutputStream(tmpFile)) {
@@ -334,28 +343,19 @@
long length = tmpFile.length();
in = new FileInputStream(tmpFile);
blob = createTemporaryBlob(in);
- executeStmt(updateDataSQL,
- new Object[]{
- blob,
- new Long(System.currentTimeMillis()),
- new Long(length),
- parentDir,
- name
- });
+ executeStmt(updateDataSQL, new Object[] {blob,
+ new Long(System.currentTimeMillis()),
+ new Long(length), parentDir, name});
}
} else {
synchronized (insertFileSQL) {
long length = tmpFile.length();
in = new FileInputStream(tmpFile);
blob = createTemporaryBlob(in);
- executeStmt(insertFileSQL,
- new Object[]{
- parentDir,
- name,
- blob,
- new Long(System.currentTimeMillis()),
- new Long(length)
- });
+ executeStmt(insertFileSQL, new Object[] {
+ parentDir, name, blob,
+ new Long(System.currentTimeMillis()),
+ new Long(length)});
}
}
} catch (Exception e) {
@@ -388,7 +388,9 @@
/**
* {@inheritDoc}
*/
- public RandomAccessOutputStream getRandomAccessOutputStream(final String filePath) throws FileSystemException, UnsupportedOperationException {
+ public RandomAccessOutputStream getRandomAccessOutputStream(
+ final String filePath) throws FileSystemException,
+ UnsupportedOperationException {
if (!initialized) {
throw new IllegalStateException("not initialized");
}
@@ -407,8 +409,10 @@
}
try {
- TransientFileFactory fileFactory = TransientFileFactory.getInstance();
- final File tmpFile = fileFactory.createTransientFile("bin", null, null);
+ TransientFileFactory fileFactory = TransientFileFactory
+ .getInstance();
+ final File tmpFile = fileFactory.createTransientFile("bin", null,
+ null);
// @todo FIXME use java.sql.Blob
@@ -429,8 +433,8 @@
}
return new RandomAccessOutputStream() {
- private final RandomAccessFile raf =
- new RandomAccessFile(tmpFile, "rw");
+ private final RandomAccessFile raf = new RandomAccessFile(
+ tmpFile, "rw");
public void close() throws IOException {
raf.close();
@@ -443,28 +447,19 @@
long length = tmpFile.length();
in = new FileInputStream(tmpFile);
blob = createTemporaryBlob(in);
- executeStmt(updateDataSQL,
- new Object[]{
- blob,
- new Long(System.currentTimeMillis()),
- new Long(length),
- parentDir,
- name
- });
+ executeStmt(updateDataSQL, new Object[] {blob,
+ new Long(System.currentTimeMillis()),
+ new Long(length), parentDir, name});
}
} else {
synchronized (insertFileSQL) {
long length = tmpFile.length();
in = new FileInputStream(tmpFile);
blob = createTemporaryBlob(in);
- executeStmt(insertFileSQL,
- new Object[]{
- parentDir,
- name,
- blob,
- new Long(System.currentTimeMillis()),
- new Long(length)
- });
+ executeStmt(insertFileSQL, new Object[] {
+ parentDir, name, blob,
+ new Long(System.currentTimeMillis()),
+ new Long(length)});
}
}
} catch (Exception e) {
@@ -495,7 +490,7 @@
raf.write(b);
}
- public void flush() /*throws IOException*/ {
+ public void flush() /* throws IOException */ {
// nop
}
@@ -503,7 +498,8 @@
raf.write(b);
}
- public void write(byte[] b, int off, int len) throws IOException {
+ public void write(byte[] b, int off, int len)
+ throws IOException {
raf.write(b, off, len);
}
};
@@ -514,31 +510,28 @@
}
}
- //----------------------------------------< oracle-specific blob handling >
+ // ----------------------------------------< 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;
- */
+ * 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, DURATION_SESSION_CONSTANT});
- Method open = blobClass.getMethod("open", new Class[]{Integer.TYPE});
- open.invoke(blob, new Object[]{MODE_READWRITE_CONSTANT});
- Method getBinaryOutputStream =
- blobClass.getMethod("getBinaryOutputStream", new Class[0]);
- OutputStream out = (OutputStream) getBinaryOutputStream.invoke(blob, null);
+ 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,
+ null);
try {
int read;
byte[] buf = new byte[8192];
@@ -562,7 +555,8 @@
*/
protected void freeTemporaryBlob(Object blob) throws Exception {
// blob.freeTemporary();
- Method freeTemporary = blobClass.getMethod("freeTemporary", new Class[0]);
+ Method freeTemporary = blobClass.getMethod("freeTemporary",
+ new Class[0]);
freeTemporary.invoke(blob, null);
}
}