You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2007/11/21 11:45:22 UTC
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...
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><param name="className" value="org.apache.jackrabbit.core.data.FileDataStore"/>
+ * <li><param name="{@link #setUrl(String) url}" value="jdbc:postgresql:test"/>
+ * <li><param name="{@link #setUser(String) user}" value="sa"/>
+ * <li><param name="{@link #setPassword(String) password}" value="sa"/>
+ * <li><param name="{@link #setDatabaseType(String) databaseType}" value="postgresql"/>
+ * <li><param name="{@link #setDriver(String) driver}" value="org.postgresql.Driver"/>
+ * <li><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