jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From thom...@apache.org
Subject svn commit: r597027 - in /jackrabbit/trunk/jackrabbit-core/src: main/java/org/apache/jackrabbit/core/data/ main/java/org/apache/jackrabbit/core/data/db/ main/java/org/apache/jackrabbit/core/persistence/bundle/ main/java/org/apache/jackrabbit/core/persi...
Date Wed, 21 Nov 2007 10:45:22 GMT
Author: thomasm
Date: Wed Nov 21 02:45:21 2007
New Revision: 597027

URL: http://svn.apache.org/viewvc?rev=597027&view=rev
Log:
JCR-1154 A database data store implementation

Added:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataRecord.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/
    jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/
    jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/db2.properties   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/derby.properties   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/h2.properties   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/mysql.properties   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/oracle.properties   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/postgresql.properties   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/sqlserver.properties   (with props)
Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/DataStore.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataRecord.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionRecoveryManager.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/DataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/DataStore.java?rev=597027&r1=597026&r2=597027&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/DataStore.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/DataStore.java Wed Nov 21 02:45:21 2007
@@ -19,6 +19,8 @@
 import java.io.InputStream;
 import java.util.Iterator;
 
+import javax.jcr.RepositoryException;
+
 /**
  * Append-only store for binary streams. A data store consists of a number
  * of identifiable data records that each contain a distinct binary stream.
@@ -71,33 +73,39 @@
     DataRecord addRecord(InputStream stream) throws DataStoreException;
 
     /**
-     * From now on, update the modified date of an object even when reading from it.
+     * From now on, update the modified date of an object even when accessing it.
      * Usually, the modified date is only updated when creating a new object, 
-     * or when a new link is added to an existing object.
+     * or when a new link is added to an existing object. When this setting is enabled,
+     * even getLength() will update the modified date.
      * 
      * @param before - update the modified date to the current time if it is older than this value
      */
-    void updateModifiedDateOnRead(long before);
+    void updateModifiedDateOnAccess(long before);
 
     /**
      * Delete objects that have a modified date older than the specified date.
      * 
-     * @param min
+     * @param min the minimum time
      * @return the number of data records deleted
+     * @throws DataStoreException 
      */
-    int deleteAllOlderThan(long min);
+    int deleteAllOlderThan(long min) throws DataStoreException;
     
     /**
      * Get all identifiers.
+     * 
+     * @return an iterator over all DataIdentifier objects
+     * @throws DataStoreException if the list could not be read
      */
-    Iterator getAllIdentifiers();
+    Iterator getAllIdentifiers() throws DataStoreException;
     
     /**
      * Initialized the data store
      * 
      * @param homeDir the home directory of the repository
+     * @throws RepositoryException 
      */
-    void init(String homeDir);
+    void init(String homeDir) throws RepositoryException;
 
     /**
      * Get the minimum size of an object that should be stored in this data store.
@@ -106,5 +114,18 @@
      * @return the minimum size
      */
     int getMinRecordLength();
+
+    /**
+     * Close the data store
+     * 
+     * @throws DataStoreException if a problem occured
+     */
+    void close() throws DataStoreException;
+    
+    /**
+     * Clear the in-use list. This is only used for testing to make the the garbage collection
+     * think that objects are no longer in use.
+     */
+    void clearInUse();
 
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataRecord.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataRecord.java?rev=597027&r1=597026&r2=597027&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataRecord.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataRecord.java Wed Nov 21 02:45:21 2007
@@ -45,19 +45,14 @@
     }
 
     /**
-     * Returns the length of the file.
-     *
-     * @return file length
+     * {@inheritDoc}
      */
     public long getLength() {
         return file.length();
     }
 
     /**
-     * Returns an input stream for reading the file.
-     *
-     * @return file input stream
-     * @throws DataStoreException if the file could not be opened
+     * {@inheritDoc}
      */
     public InputStream getStream() throws DataStoreException {
         try {

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java?rev=597027&r1=597026&r2=597027&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java Wed Nov 21 02:45:21 2007
@@ -252,7 +252,7 @@
     /**
      * {@inheritDoc}
      */
-    public void updateModifiedDateOnRead(long before) {
+    public void updateModifiedDateOnAccess(long before) {
         minModifiedDate = before;
     }
     
@@ -313,8 +313,7 @@
     }
     
     /**
-     * Clear the in-use list. This is only used for testing to make the the garbage collection
-     * think that objects are no longer in use.
+     * {@inheritDoc}
      */
     public void clearInUse() {
         inUse.clear();
@@ -352,6 +351,12 @@
      */
     public void setMinRecordLength(int minRecordLength) {
         this.minRecordLength = minRecordLength;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void close() {
     }
 
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java?rev=597027&r1=597026&r2=597027&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java Wed Nov 21 02:45:21 2007
@@ -32,7 +32,6 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.Value;
 import javax.jcr.Workspace;
 import javax.jcr.observation.Event;
 import javax.jcr.observation.EventIterator;
@@ -43,7 +42,7 @@
  * nodes and reads the binary properties. To detect nodes that are moved while
  * the scan runs, event listeners are started. Like the well known garbage
  * collection in Java, the items that are still in use are marked. Currently
- * this achived by updating the modified date of the entries. Newly added
+ * this achieved by updating the modified date of the entries. Newly added
  * entries are detected because the modified date is changed when they are
  * added.
  * 
@@ -93,7 +92,7 @@
             RepositoryImpl rep = (RepositoryImpl) session.getRepository();
             store = rep.getDataStore();
             startScanTimestamp = now;
-            store.updateModifiedDateOnRead(startScanTimestamp);
+            store.updateModifiedDateOnAccess(startScanTimestamp);
         }
 
         // add a listener to get 'new' nodes
@@ -161,12 +160,9 @@
                     rememberNode(n.getPath());
                 }
                 if (p.getDefinition().isMultiple()) {
-                    Value[] list = p.getValues();
-                    for (int i = 0; i < list.length; i++) {
-                        list[i].getStream().close();
-                    }
+                    p.getLengths();
                 } else {
-                    p.getStream().close();
+                    p.getLength();
                 }
             }
         }

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataRecord.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataRecord.java?rev=597027&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataRecord.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataRecord.java Wed Nov 21 02:45:21 2007
@@ -0,0 +1,64 @@
+/*
+ * 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.data.db;
+
+import org.apache.jackrabbit.core.data.AbstractDataRecord;
+import org.apache.jackrabbit.core.data.DataIdentifier;
+import org.apache.jackrabbit.core.data.DataStoreException;
+
+import java.io.InputStream;
+
+/**
+ * Data record that is stored in a database
+ */
+public class DbDataRecord extends AbstractDataRecord {
+    
+    private final DbDataStore store;
+    private final long length;
+    private long lastModified;
+
+    /**
+     * Creates a data record based on the given identifier and length.
+     *
+     * @param identifier data identifier
+     * @param length the length
+     * @param file file that contains the binary stream
+     */
+    public DbDataRecord(DbDataStore store, DataIdentifier identifier, long length, long lastModified) {
+        super(identifier);
+        this.store = store;
+        this.length = length;
+        this.lastModified = lastModified;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public long getLength() throws DataStoreException {
+        lastModified = store.touch(getIdentifier(), lastModified);
+        return length;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public InputStream getStream() throws DataStoreException {
+        lastModified = store.touch(getIdentifier(), lastModified);
+        return store.getInputStream(getIdentifier());
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataRecord.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java?rev=597027&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java Wed Nov 21 02:45:21 2007
@@ -0,0 +1,604 @@
+/*
+ * 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.data.db;
+
+import org.apache.jackrabbit.core.data.DataIdentifier;
+import org.apache.jackrabbit.core.data.DataRecord;
+import org.apache.jackrabbit.core.data.DataStore;
+import org.apache.jackrabbit.core.data.DataStoreException;
+import org.apache.jackrabbit.core.persistence.bundle.util.ConnectionRecoveryManager;
+import org.apache.jackrabbit.core.persistence.bundle.util.TrackingInputStream;
+import org.apache.jackrabbit.core.persistence.bundle.util.ConnectionRecoveryManager.StreamWrapper;
+import org.apache.jackrabbit.uuid.UUID;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.ref.WeakReference;
+import java.security.DigestInputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.WeakHashMap;
+
+/**
+ * A data store implementation that stores the records in a database using JDBC.
+ * 
+ * Configuration:<br>
+ * <ul>
+ * <li>&lt;param name="className" value="org.apache.jackrabbit.core.data.FileDataStore"/>
+ * <li>&lt;param name="{@link #setUrl(String) url}" value="jdbc:postgresql:test"/>
+ * <li>&lt;param name="{@link #setUser(String) user}" value="sa"/>
+ * <li>&lt;param name="{@link #setPassword(String) password}" value="sa"/>
+ * <li>&lt;param name="{@link #setDatabaseType(String) databaseType}" value="postgresql"/>
+ * <li>&lt;param name="{@link #setDriver(String) driver}" value="org.postgresql.Driver"/>
+ * <li>&lt;param name="{@link #setMinRecordLength(int) minRecordLength}" value="1024"/>
+ * </ul>
+ * 
+ * <p>
+ * Only URL, user name and password usually need to be set. 
+ * The remaining settings are generated using the database URL sub-protocol from the
+ * database type resource file.
+ * <p>
+ * A three level directory structure is used to avoid placing too many
+ * files in a single directory. The chosen structure is designed to scale
+ * up to billions of distinct records.
+ */
+public class DbDataStore implements DataStore {
+    
+    /**
+     * The digest algorithm used to uniquely identify records.
+     */
+    private static final String DIGEST = "SHA-1";
+    
+    /**
+     * Logger instance
+     */
+    private static Logger log = LoggerFactory.getLogger(DbDataStore.class);    
+    
+    /**
+     * The default value for the minimum object size.
+     */
+    private static final int DEFAULT_MIN_RECORD_LENGTH = 100;
+    
+    /**
+     * The minimum modified date. If a file is accessed (read or write) with a modified date 
+     * older than this value, the modified date is updated to the current time.
+     */
+    private long minModifiedDate;
+    
+    /**
+     * The database URL used.
+     */
+    private String url;
+    
+    /**
+     * The database driver.
+     */
+    private String driver;
+    
+    /**
+     * The user name.
+     */
+    private String user;
+    
+    /**
+     * The password
+     */
+    private String password;
+    
+    /**
+     * The database type used.
+     */
+    private String databaseType;
+    
+    /**
+     * The minimum size of an object that should be stored in this data store.
+     */
+    private int minRecordLength = DEFAULT_MIN_RECORD_LENGTH;
+    
+    private ConnectionRecoveryManager conn;
+    
+    private static final String TEMP_PREFIX = "TEMP_";
+    
+    private String tableSQL = "DATASTORE";
+    private String createTableSQL = 
+        "CREATE TABLE DATASTORE(ID VARCHAR(255) PRIMARY KEY, LENGTH BIGINT, LAST_MODIFIED BIGINT, DATA BLOB)";
+    private String insertTempSQL = 
+        "INSERT INTO DATASTORE VALUES(?, 0, ?, NULL)";
+    private String updateDataSQL = 
+        "UPDATE DATASTORE SET DATA=? WHERE ID=?";
+    private String updateLastModifiedSQL = 
+        "UPDATE DATASTORE SET LAST_MODIFIED=? WHERE ID=? AND LAST_MODIFIED<?";
+    private String updateSQL = 
+        "UPDATE DATASTORE SET ID=?, LENGTH=?, LAST_MODIFIED=? WHERE ID=? AND NOT EXISTS(SELECT ID FROM DATASTORE WHERE ID=?)";
+    private String deleteSQL = 
+        "DELETE FROM DATASTORE WHERE ID=?";
+    private String deleteOlderSQL = 
+        "DELETE FROM DATASTORE WHERE LAST_MODIFIED<?";
+    private String selectMetaSQL = 
+        "SELECT LENGTH, LAST_MODIFIED FROM DATASTORE WHERE ID=?";
+    private String selectAllSQL = 
+        "SELECT ID FROM DATASTORE";
+    private String selectDataSQL = 
+        "SELECT DATA FROM DATASTORE WHERE ID=?";
+    private String storeStream = STORE_TEMP_FILE;
+    
+    // write to a temporary file to get the length (slow, but always works)
+    // this is the default setting
+    private static final String STORE_TEMP_FILE = "tempFile";
+    
+    // call PreparedStatement.setBinaryStream(..., -1)
+    private static final String STORE_SIZE_MINUS_ONE = "-1";
+    
+    // call PreparedStatement.setBinaryStream(..., Integer.MAX_VALUE)
+    private static final String STORE_SIZE_MAX = "max";
+    
+    /**
+     * All data identifiers that are currently in use are in this set until they are garbage collected.
+     */
+    private WeakHashMap inUse = new WeakHashMap();    
+
+    /**
+     * {@inheritDoc}
+     */
+    public synchronized DataRecord addRecord(InputStream stream) throws DataStoreException {
+        conn.setAutoReconnect(false);
+        String id = null, tempId = null;            
+        long now;            
+        for (int i = 0; i < ConnectionRecoveryManager.TRIALS; i++) {
+            try {
+                now = System.currentTimeMillis();
+                id = UUID.randomUUID().toString();
+                tempId = TEMP_PREFIX + id;
+                PreparedStatement prep = conn.executeStmt(selectMetaSQL, new Object[]{tempId});
+                ResultSet rs = prep.getResultSet();
+                if (rs.next()) {
+                    // re-try in the very, very unlikely event that the row already exists
+                    continue;
+                }
+                conn.executeStmt(insertTempSQL, new Object[]{tempId, new Long(now)});
+                break;
+            } catch (Exception e) {
+                throw convert("Can not insert new record", e);
+            }
+        }
+        if (id == null) {
+            String msg = "Can not create new record";
+            log.error(msg);
+            throw new DataStoreException(msg);
+        }
+        ResultSet rs = null;
+        try {
+            MessageDigest digest = getDigest();
+            DigestInputStream dIn = new DigestInputStream(stream, digest);
+            TrackingInputStream in = new TrackingInputStream(dIn);
+            File temp = null;
+            InputStream fileInput = null;
+            StreamWrapper wrapper;
+            if (STORE_SIZE_MINUS_ONE.equals(storeStream)) {
+                wrapper = new StreamWrapper(in, -1);
+            } else if (STORE_SIZE_MAX.equals(storeStream)) {
+                    wrapper = new StreamWrapper(in, Integer.MAX_VALUE);
+            } else if (STORE_TEMP_FILE.equals(storeStream)) {
+                int length = 0;
+                temp = File.createTempFile("dbRecord", null);
+                OutputStream out = new FileOutputStream(temp);
+                byte[] b = new byte[4096];
+                while (true) {
+                    int n = in.read(b);
+                    if (n < 0) {
+                        break;
+                    }
+                    out.write(b, 0, n);
+                    length += n;
+                }
+                out.close();
+                fileInput = new BufferedInputStream(new FileInputStream(temp));
+                wrapper = new StreamWrapper(fileInput, length);
+            } else {
+                throw new DataStoreException("Unsupported stream store algorithm: " + storeStream);
+            }
+            conn.executeStmt(updateDataSQL, new Object[]{wrapper, tempId});
+            now = System.currentTimeMillis();
+            long length = in.getPosition();
+            DataIdentifier identifier = new DataIdentifier(digest.digest());
+            id = identifier.toString();
+            // UPDATE DATASTORE SET ID=?, LENGTH=?, LAST_MODIFIED=? 
+            // WHERE ID=? 
+            // AND NOT EXISTS(SELECT ID FROM DATASTORE WHERE ID=?)
+            PreparedStatement prep = conn.executeStmt(updateSQL, new Object[]{
+                    id, new Long(length), new Long(now), 
+                    tempId, id});
+            int count = prep.getUpdateCount();
+            if (temp != null) {
+                fileInput.close();
+                temp.delete();
+            }
+            if (count == 0) {
+                // update count is 0, meaning such a row already exists
+                // DELETE FROM DATASTORE WHERE ID=?
+                conn.executeStmt(deleteSQL, new Object[]{tempId});
+                // SELECT LENGTH, LAST_MODIFIED FROM DATASTORE WHERE ID=?
+                prep = conn.executeStmt(selectMetaSQL, new Object[]{id});
+                rs = prep.getResultSet();
+                if (rs.next()) {
+                    long oldLength = rs.getLong(1);
+                    long lastModified = rs.getLong(2);
+                    if (oldLength != length) {
+                        String msg = DIGEST + " collision: temp=" + tempId + " id=" + id + " length=" + length + " oldLength=" + oldLength;
+                        log.error(msg);
+                        throw new DataStoreException(msg);
+                    }
+                    touch(identifier, lastModified);
+                }
+            }
+            usesIdentifier(identifier);
+            DbDataRecord record = new DbDataRecord(this, identifier, length, now);
+            conn.setAutoReconnect(true);
+            return record;
+        } catch (Exception e) {
+            throw convert("Can not insert new record", e);
+        } finally {
+            conn.closeSilently(rs);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public synchronized int deleteAllOlderThan(long min) throws DataStoreException {
+        try {
+            Iterator it = inUse.keySet().iterator();
+            while (it.hasNext()) {
+                DataIdentifier identifier = (DataIdentifier) it.next();
+                if (identifier != null) {
+                    touch(identifier, 0);
+                }
+            }
+            // DELETE FROM DATASTORE WHERE LAST_MODIFIED<?
+            PreparedStatement prep = conn.executeStmt(deleteOlderSQL, new Long[]{new Long(min)});
+            return prep.getUpdateCount();
+        } catch (Exception e) {
+            throw convert("Can not delete records", e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Iterator getAllIdentifiers() throws DataStoreException {
+        ArrayList list = new ArrayList();
+        ResultSet rs = null;
+        try {
+            // SELECT ID FROM DATASTORE
+            PreparedStatement prep = conn.executeStmt(selectAllSQL, new Object[0]);
+            rs = prep.getResultSet();
+            while (rs.next()) {
+                String id = rs.getString(1);
+                if (!id.startsWith(TEMP_PREFIX)) {
+                    DataIdentifier identifier = new DataIdentifier(id);
+                    list.add(identifier);
+                }
+            }
+            return list.iterator();
+        } catch (Exception e) {
+            throw convert("Can not read records", e);
+        } finally {
+            conn.closeSilently(rs);
+        }        
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getMinRecordLength() {
+        return minRecordLength;
+    }
+
+    /**
+     * Set the minimum object length.
+     * 
+     * @param minRecordLength the length
+     */
+    public void setMinRecordLength(int minRecordLength) {
+        this.minRecordLength = minRecordLength;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public synchronized DataRecord getRecord(DataIdentifier identifier) throws DataStoreException {
+        usesIdentifier(identifier);
+        ResultSet rs = null;
+        try {
+            // SELECT LENGTH, LAST_MODIFIED FROM DATASTORE WHERE ID = ?
+            String id = identifier.toString();
+            PreparedStatement prep = conn.executeStmt(selectMetaSQL, new Object[]{id});
+            rs = prep.getResultSet();
+            if (!rs.next()) {
+                throw new DataStoreException("Record not found: " + identifier);
+            }
+            long length = rs.getLong(1);
+            long lastModified = rs.getLong(2);
+            touch(identifier, lastModified);
+            return new DbDataRecord(this, identifier, length, lastModified);
+        } catch (Exception e) {
+            throw convert("Can not read identifier " + identifier, e);
+        } finally {
+            conn.closeSilently(rs);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public synchronized void init(String homeDir) throws DataStoreException {
+        try {
+            initDatabaseType();
+            conn = new ConnectionRecoveryManager(false, driver, url, user, password);
+            conn.setAutoReconnect(true);
+            DatabaseMetaData meta = conn.getConnection().getMetaData();
+            ResultSet rs = meta.getTables(null, null, tableSQL, null);
+            boolean exists = rs.next();
+            rs.close();
+            if (!exists) {
+                conn.executeStmt(createTableSQL, null);
+            }
+        } catch (Exception e) {
+            throw convert("Can not init data store, driver=" + driver + " url=" + url + " user=" + user, e);
+        }
+    }
+    
+    private void initDatabaseType() throws DataStoreException {
+        boolean failIfNotFound;
+        if (databaseType == null) {
+            if (!url.startsWith("jdbc:")) {
+                return;
+            }
+            failIfNotFound = false;
+            int start = "jdbc:".length();
+            int end = url.indexOf(':', start);
+            databaseType = url.substring(start, end);
+        } else {
+            failIfNotFound = true;
+        }
+        InputStream in = DbDataStore.class.getResourceAsStream(databaseType + ".properties");
+        if (in == null) {
+            if (failIfNotFound) {
+                String msg = "Configuration error: The resource '" + databaseType + ".properties' could not be found; Please verify the databaseType property";
+                log.debug(msg);
+                throw new DataStoreException(msg);
+            } else {
+                return;
+            }
+        }
+        Properties prop = new Properties();
+        try {
+            prop.load(new BufferedInputStream(in));
+        } catch (IOException e) {
+            String msg = "Configuration error: Could not read properties '" + databaseType + ".properties'";
+            log.debug(msg);
+            throw new DataStoreException(msg);
+        }
+        if (driver == null) {
+            driver = prop.getProperty("driver", driver);
+        }
+        tableSQL = prop.getProperty("table", tableSQL);
+        createTableSQL = prop.getProperty("createTable", createTableSQL);
+        insertTempSQL = prop.getProperty("insertTemp", insertTempSQL);
+        updateDataSQL = prop.getProperty("updateData", updateDataSQL);
+        updateLastModifiedSQL = prop.getProperty("updateLastModified", updateLastModifiedSQL);
+        updateSQL = prop.getProperty("update", updateSQL);
+        deleteSQL = prop.getProperty("delete", deleteSQL);
+        deleteOlderSQL = prop.getProperty("deleteOlder", deleteOlderSQL);
+        selectMetaSQL = prop.getProperty("selectMeta", selectMetaSQL);
+        selectAllSQL = prop.getProperty("selectAll", selectAllSQL);
+        selectDataSQL = prop.getProperty("selectData", selectDataSQL);
+        storeStream = prop.getProperty("storeStream", storeStream);
+        if (STORE_SIZE_MINUS_ONE.equals(storeStream)) {
+        } else if (STORE_TEMP_FILE.equals(storeStream)) {
+        } else if (STORE_SIZE_MAX.equals(storeStream)) {            
+        } else {
+            String msg = "Unsupported Stream store mechanism: " + storeStream
+                    + " supported are: " + STORE_SIZE_MINUS_ONE + ", "
+                    + STORE_TEMP_FILE + ", " + STORE_SIZE_MAX;
+            log.debug(msg);
+            throw new DataStoreException(msg);
+        }
+    }
+
+    private DataStoreException convert(String cause, Exception e) {
+        log.warn(cause, e);
+        return new DataStoreException(cause, e);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void updateModifiedDateOnAccess(long before) {
+        log.debug("Update modifiedDate on access before " + before);
+        minModifiedDate = before;
+    }
+
+    synchronized long touch(DataIdentifier identifier, long lastModified) throws DataStoreException {
+        usesIdentifier(identifier);
+        if (lastModified < minModifiedDate) {
+            long now = System.currentTimeMillis();
+            Long n = new Long(now);
+            // UPDATE DATASTORE SET LAST_MODIFIED = ? WHERE ID = ? AND LAST_MODIFIED < ?
+            try {
+                conn.executeStmt(updateLastModifiedSQL, new Object[]{
+                        n, identifier.toString(), n
+                });
+                return now;
+            } catch (Exception e) {
+                throw convert("Can not update lastModified", e);
+            }
+        }
+        return lastModified;
+    }
+
+    /**
+     * {@inheritDoc}
+     */    
+    public InputStream getInputStream(DataIdentifier identifier) throws DataStoreException {
+        try {
+            // SELECT DATA FROM DATASTORE WHERE ID = ?
+            String id = identifier.toString();
+            PreparedStatement prep = conn.executeStmt(selectDataSQL, new Object[]{id});
+            ResultSet rs = prep.getResultSet();
+            if (!rs.next()) {
+                throw new DataStoreException("Record not found: " + identifier);
+            }
+            return rs.getBinaryStream(1);
+        } catch (Exception e) {
+            throw convert("Can not read identifier " + identifier, e);
+        }
+    }
+
+    /**
+     * Get the database type (if set).
+     * @return the database type
+     */
+    public String getDatabaseType() {
+        return databaseType;
+    }
+
+    /** 
+     * Set the database type. By default the sub-protocol of the JDBC database URL is used if it is not set.
+     * It must match the resource file [databaseType].properties. Example: mysql.
+     * 
+     * @param databaseType
+     */
+    public void setDatabaseType(String databaseType) {
+        this.databaseType = databaseType;
+    }
+
+    /**
+     * Get the database driver
+     * 
+     * @return the driver
+     */
+    public String getDriver() {
+        return driver;
+    }
+
+    /**
+     * Set the database driver class name.
+     * If not set, the default driver class name for the database type is used, 
+     * as set in the [databaseType].properties resource; key 'driver'.
+     * 
+     * @param driver
+     */
+    public void setDriver(String driver) {
+        this.driver = driver;
+    }
+
+    /**
+     * Get the password.
+     * 
+     * @return the password
+     */
+    public String getPassword() {
+        return password;
+    }
+
+    /**
+     * Set the password.
+     * 
+     * @param password
+     */
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    /**
+     * Get the database URL.
+     * 
+     * @return the URL
+     */
+    public String getUrl() {
+        return url;
+    }
+
+    /**
+     * Set the database URL.
+     * Example: jdbc:postgresql:test
+     * 
+     * @param url
+     */
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    /**
+     * Get the user name.
+     * 
+     * @return the user name
+     */
+    public String getUser() {
+        return user;
+    }
+
+    /**
+     * Set the user name.
+     * 
+     * @param user
+     */
+    public void setUser(String user) {
+        this.user = user;
+    }
+    
+    /**
+     * {@inheritDoc}
+     */
+    public void close() {
+        conn.close();
+    }
+    
+    private void usesIdentifier(DataIdentifier identifier) {
+        inUse.put(identifier, new WeakReference(identifier));
+    }
+    
+    /**
+     * {@inheritDoc}
+     */
+    public void clearInUse() {
+        inUse.clear();
+    }    
+    
+    private synchronized MessageDigest getDigest() throws DataStoreException {
+        try {
+            return MessageDigest.getInstance(DIGEST);
+        } catch (NoSuchAlgorithmException e) {
+            throw convert("No such algorithm: " + DIGEST, e);
+        }
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java?rev=597027&r1=597026&r2=597027&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java Wed Nov 21 02:45:21 2007
@@ -63,16 +63,16 @@
  * included in the bundle since they are addressed by the target id.
  * <p/>
  * Some strings like namespaces and local names are additionally managed by
- * seperate indexes. only the index number is serialized to the records which
+ * separate indexes. only the index number is serialized to the records which
  * reduces the amount of memory used.
  * <p/>
  * Special treatment is performed for the properties "jcr:uuid", "jcr:primaryType"
  * and "jcr:mixinTypes". As they are also stored in the node state they are not
  * included in the bundle but generated when required.
  * <p/>
- * In order to increase performance, there are 2 caches maintained. One ist the
+ * In order to increase performance, there are 2 caches maintained. One is the
  * {@link BundleCache} that caches already loaded bundles. The other is the
- * {@link LRUNodeIdCache} that caches non-existent bundles. This is usefull
+ * {@link LRUNodeIdCache} that caches non-existent bundles. This is useful
  * because a lot of {@link #exists(NodeId)} calls are issued that would result
  * in a useless SQL execution if the desired bundle does not exist.
  * <p/>
@@ -111,7 +111,7 @@
     /** the cache of loaded bundles */
     private BundleCache bundles;
 
-    /** the cahce of non-existent bundles */
+    /** the cache of non-existent bundles */
     private LRUNodeIdCache missing;
 
     /** definition id of the jcr:uuid property */
@@ -126,7 +126,7 @@
     /** the persistence manager context */
     protected PMContext context;
 
-    /** default size of the bunlde cache */
+    /** default size of the bundle cache */
     private long bundleCacheSize = 8 * 1024 * 1024;
 
     /**
@@ -331,7 +331,7 @@
      * Loads a bundle from the underlying system.
      *
      * @param id the node id of the bundle
-     * @return the loaded bunlde or <code>null</code> if the bundle does not
+     * @return the loaded bundle or <code>null</code> if the bundle does not
      *         exist.
      * @throws ItemStateException if an error while loading occurs.
      */
@@ -375,7 +375,7 @@
             throws NoSuchItemStateException, ItemStateException;
 
     /**
-     * Deletes the node references from the undelying system.
+     * Deletes the node references from the underlying system.
      *
      * @param refs the node references to destroy.
      * @throws ItemStateException if an error while destroying occurs.
@@ -484,7 +484,7 @@
     /**
      * {@inheritDoc}
      *
-     * Checks the existance via the appropriate NodePropBundle.
+     * Checks the existence via the appropriate NodePropBundle.
      */
     public synchronized boolean exists(NodeId id) throws ItemStateException {
         // anticipating a load followed by a exists
@@ -653,7 +653,7 @@
      * Gets the bundle for the given nodeid.
      *
      * @param id the id of the bundle to retrieve.
-     * @return the bundle or <code>null</code> if the bunlde does not exist
+     * @return the bundle or <code>null</code> if the bundle does not exist
      *
      * @throws ItemStateException if an error occurs.
      */

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionRecoveryManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionRecoveryManager.java?rev=597027&r1=597026&r2=597027&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionRecoveryManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionRecoveryManager.java Wed Nov 21 02:45:21 2007
@@ -101,7 +101,7 @@
      * Number of reconnection attempts per method call. Only
      * used if <code>block == false</code>.
      */
-    private static final int TRIALS = 20;
+    public static final int TRIALS = 20;
 
     /**
      * The map of prepared statements (key: SQL stmt, value: prepared stmt).
@@ -234,7 +234,7 @@
      * @throws SQLException if an error occurs
      * @throws RepositoryException if the database driver could not be loaded
      */
-    public Statement executeStmt(String sql, Object[] params) throws SQLException, RepositoryException {
+    public PreparedStatement executeStmt(String sql, Object[] params) throws SQLException, RepositoryException {
         return executeStmt(sql, params, false, 0);
     }    
 
@@ -249,7 +249,7 @@
      * @throws SQLException if an error occurs
      * @throws RepositoryException if the database driver could not be loaded
      */
-    public synchronized Statement executeStmt(String sql, Object[] params, boolean returnGeneratedKeys, int maxRows) throws SQLException, RepositoryException {
+    public synchronized PreparedStatement executeStmt(String sql, Object[] params, boolean returnGeneratedKeys, int maxRows) throws SQLException, RepositoryException {
         int trials = 2;
         SQLException lastException  = null;
         do {
@@ -274,7 +274,7 @@
      * @throws SQLException if an error occurs
      * @throws RepositoryException if the database driver could not be loaded
      */
-    private Statement executeStmtInternal(String sql, Object[] params, boolean returnGeneratedKeys, int maxRows) throws SQLException, RepositoryException {
+    private PreparedStatement executeStmtInternal(String sql, Object[] params, boolean returnGeneratedKeys, int maxRows) throws SQLException, RepositoryException {
         try {
             String key = sql;
             if (returnGeneratedKeys) {
@@ -326,11 +326,13 @@
      */
     private void setupConnection() throws SQLException, RepositoryException {
         try {
-            Class driverClass = Class.forName(driver);
-            // Workaround for Apache Derby:
-            // The JDBC specification recommends the Class.ForName method without the .newInstance() method call, 
-            // but adding the newInstance() guarantees that Derby will be booted on any Java Virtual Machine.
-            driverClass.newInstance();
+            if (driver != null && driver.length() > 0) {
+                Class driverClass = Class.forName(driver);
+                // Workaround for Apache Derby:
+                // The JDBC specification recommends the Class.ForName method without the .newInstance() method call, 
+                // but adding the newInstance() guarantees that Derby will be booted on any Java Virtual Machine.
+                driverClass.newInstance();
+            }
         } catch (Throwable e) {
             throw new RepositoryException("Could not load or initialize the database driver class " + driver, e);
         }
@@ -356,13 +358,17 @@
      * @return the executed Statement
      * @throws SQLException on error
      */
-    private Statement executeStmtInternal(Object[] params, PreparedStatement stmt) throws SQLException {
-        for (int i = 0; i < params.length; i++) {
-            if (params[i] instanceof StreamWrapper) {
-                StreamWrapper wrapper = (StreamWrapper) params[i];
+    private PreparedStatement executeStmtInternal(Object[] params, PreparedStatement stmt) throws SQLException {
+        for (int i = 0; params != null && i < params.length; i++) {
+            Object p = params[i];
+            if (p instanceof StreamWrapper) {
+                StreamWrapper wrapper = (StreamWrapper) p;
                 stmt.setBinaryStream(i + 1, wrapper.stream, (int) wrapper.size);
+            } else if (p instanceof InputStream) {
+                InputStream stream = (InputStream) p;
+                stmt.setBinaryStream(i + 1, stream, -1);
             } else {
-                stmt.setObject(i + 1, params[i]);
+                stmt.setObject(i + 1, p);
             }
         }
         stmt.execute();
@@ -464,7 +470,7 @@
 
         /**
          * Creates a wrapper for the given InputStream that can
-         * savely be passed as a parameter to the <code>executeStmt</code>
+         * safely be passed as a parameter to the <code>executeStmt</code>
          * methods in the {@link ConnectionRecoveryManager} class.
          *
          * @param in the InputStream to wrap
@@ -473,6 +479,16 @@
         public StreamWrapper(InputStream in, long size) {
             this.stream = in;
             this.size = size;
+        }
+    }
+
+    public void closeSilently(ResultSet rs) {
+        if (rs != null) {
+            try {
+                rs.close();
+            } catch (SQLException e) {
+                // ignore
+            }
         }
     }
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java?rev=597027&r1=597026&r2=597027&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java Wed Nov 21 02:45:21 2007
@@ -74,7 +74,7 @@
         LOG.debug("stop scanning; currently " + count + " identifiers");
         gc.stopScan();
         LOG.debug("deleting...");
-        ((FileDataStore) gc.getDataStore()).clearInUse();
+        gc.getDataStore().clearInUse();
         assertTrue(gc.deleteUnused() > 0);
         int count2 = listIdentifiers(gc);
         assertEquals(count - 1, count2);
@@ -88,12 +88,12 @@
         gc.scan(session);
         gc.stopScan();
         if (all) {
-            ((FileDataStore) gc.getDataStore()).clearInUse();
+            gc.getDataStore().clearInUse();
         }
         gc.deleteUnused();
     }
     
-    private int listIdentifiers(GarbageCollector gc) {
+    private int listIdentifiers(GarbageCollector gc) throws DataStoreException {
         LOG.debug("identifiers:");
         Iterator it = gc.getDataStore().getAllIdentifiers();
         int count = 0;

Added: jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/db2.properties
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/db2.properties?rev=597027&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/db2.properties (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/db2.properties Wed Nov 21 02:45:21 2007
@@ -0,0 +1 @@
+driver=COM.ibm.db2.jdbc.net.DB2Driver

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/db2.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/derby.properties
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/derby.properties?rev=597027&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/derby.properties (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/derby.properties Wed Nov 21 02:45:21 2007
@@ -0,0 +1 @@
+driver=org.apache.derby.jdbc.EmbeddedDriver

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/derby.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/h2.properties
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/h2.properties?rev=597027&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/h2.properties (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/h2.properties Wed Nov 21 02:45:21 2007
@@ -0,0 +1,2 @@
+driver=org.h2.Driver
+storeStream=-1

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/h2.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/mysql.properties
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/mysql.properties?rev=597027&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/mysql.properties (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/mysql.properties Wed Nov 21 02:45:21 2007
@@ -0,0 +1 @@
+driver=com.mysql.jdbc.Driver

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/mysql.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/oracle.properties
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/oracle.properties?rev=597027&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/oracle.properties (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/oracle.properties Wed Nov 21 02:45:21 2007
@@ -0,0 +1 @@
+driver=oracle.jdbc.OracleDriver

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/oracle.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/postgresql.properties
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/postgresql.properties?rev=597027&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/postgresql.properties (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/postgresql.properties Wed Nov 21 02:45:21 2007
@@ -0,0 +1 @@
+driver=org.postgresql.Driver

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/postgresql.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/sqlserver.properties
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/sqlserver.properties?rev=597027&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/sqlserver.properties (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/sqlserver.properties Wed Nov 21 02:45:21 2007
@@ -0,0 +1 @@
+driver=com.microsoft.sqlserver.jdbc.SQLServerDriver

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/resources/org/apache/jackrabbit/core/data/db/sqlserver.properties
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message