Skip to content

Commit

Permalink
Add tableName configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
rmaucher committed Dec 5, 2024
1 parent 22c7b27 commit 323071f
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 30 deletions.
78 changes: 53 additions & 25 deletions java/org/apache/catalina/servlets/DataSourcePropertyStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
import org.w3c.dom.Node;

/**
* WebDAV dead properties storage backed by a DataSource. Usually table and column names
* are configurable, but for simplicity this is not the case.
* WebDAV dead properties storage using a DataSource.
* <p>
* The schema is:
* table properties ( path, namespace, name, node )
* path: the resource path
Expand All @@ -55,38 +55,58 @@ public class DataSourcePropertyStore implements WebdavServlet.PropertyStore {
protected static final StringManager sm = StringManager.getManager(DataSourcePropertyStore.class);
private final Log log = LogFactory.getLog(DataSourcePropertyStore.class);

private static String ADD_PROPERTY_STMT = "INSERT INTO properties (path, namespace, name, node) VALUES (?, ?, ?, ?)";
private static String SET_PROPERTY_STMT = "UPDATE properties SET node = ? WHERE path = ? AND namespace = ? AND name = ?";
private static String REMOVE_ALL_PROPERTIES_STMT = "DELETE FROM properties WHERE path = ?";
private static String REMOVE_PROPERTY_STMT = "DELETE FROM properties WHERE path = ? AND namespace = ? AND name = ?";
private static String GET_PROPERTY_STMT = "SELECT node FROM properties WHERE path = ? AND namespace = ? AND name = ?";
private static String GET_PROPERTIES_NAMES_STMT = "SELECT namespace, name FROM properties WHERE path = ?";
private static String GET_PROPERTIES_STMT = "SELECT namespace, name, node FROM properties WHERE path = ?";
private static String GET_PROPERTIES_NODES_STMT = "SELECT node FROM properties WHERE path = ?";

/**
* DataSource JNDI name, will be prefixed with java:comp/env for the lookup.
*/
private String dataSourceName = "WebdavPropertyStore";

/**
* Table name.
*/
private String tableName = "properties";

private String addPropertyStatement;
private String setPropertyStatement;
private String removeAllPropertiesStatement;
private String removePropertyStatement;
private String getPropertyStatement;
private String getPropertiesNameStatement;
private String getPropertiesStatement;
private String getPropertiesNodeStatement;

private final ReentrantReadWriteLock dbLock = new ReentrantReadWriteLock();
private final Lock dbReadLock = dbLock.readLock();
private final Lock dbWriteLock = dbLock.writeLock();

/**
* @return the dataSourceName
* @return the DataSource JNDI name, will be prefixed with java:comp/env for the lookup.
*/
public String getDataSourceName() {
return this.dataSourceName;
}

/**
* @param dataSourceName the dataSourceName to set
* @param dataSourceName the DataSource JNDI name, will be prefixed with
* java:comp/env for the lookup.
*/
public void setDataSourceName(String dataSourceName) {
this.dataSourceName = dataSourceName;
}

/**
* @return the table name that will be used in the database
*/
public String getTableName() {
return this.tableName;
}

/**
* @param tableName the table name to use in the database
*/
public void setTableName(String tableName) {
this.tableName = tableName;
}

/**
* DataSource instance being used.
*/
Expand All @@ -101,6 +121,14 @@ public void init() {
throw new IllegalArgumentException(sm.getString("webdavservlet.dataSourceStore.noDataSource", dataSourceName), e);
}
}
addPropertyStatement = "INSERT INTO " + tableName + " (path, namespace, name, node) VALUES (?, ?, ?, ?)";
setPropertyStatement = "UPDATE " + tableName + " SET node = ? WHERE path = ? AND namespace = ? AND name = ?";
removeAllPropertiesStatement = "DELETE FROM " + tableName + " WHERE path = ?";
removePropertyStatement = "DELETE FROM " + tableName + " WHERE path = ? AND namespace = ? AND name = ?";
getPropertyStatement = "SELECT node FROM " + tableName + " WHERE path = ? AND namespace = ? AND name = ?";
getPropertiesNameStatement = "SELECT namespace, name FROM " + tableName + " WHERE path = ?";
getPropertiesStatement = "SELECT namespace, name, node FROM " + tableName + " WHERE path = ?";
getPropertiesNodeStatement = "SELECT node FROM " + tableName + " WHERE path = ?";
}

@Override
Expand All @@ -118,7 +146,7 @@ public void copy(String source, String destination) {
}
dbWriteLock.lock();
try (Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(GET_PROPERTIES_STMT)) {
PreparedStatement statement = connection.prepareStatement(getPropertiesStatement)) {
statement.setString(1, source);
if (statement.execute()) {
ResultSet rs = statement.getResultSet();
Expand All @@ -127,7 +155,7 @@ public void copy(String source, String destination) {
String name = rs.getString(2);
String node = rs.getString(3);
boolean found = false;
try (PreparedStatement statement2 = connection.prepareStatement(GET_PROPERTY_STMT)) {
try (PreparedStatement statement2 = connection.prepareStatement(getPropertyStatement)) {
statement2.setString(1, destination);
statement2.setString(2, namespace);
statement2.setString(3, name);
Expand All @@ -139,15 +167,15 @@ public void copy(String source, String destination) {
}
}
if (found) {
try (PreparedStatement statement2 = connection.prepareStatement(SET_PROPERTY_STMT)) {
try (PreparedStatement statement2 = connection.prepareStatement(setPropertyStatement)) {
statement2.setString(1, node);
statement2.setString(2, destination);
statement2.setString(3, namespace);
statement2.setString(4, name);
statement2.execute();
}
} else {
try (PreparedStatement statement2 = connection.prepareStatement(ADD_PROPERTY_STMT)) {
try (PreparedStatement statement2 = connection.prepareStatement(addPropertyStatement)) {
statement2.setString(1, destination);
statement2.setString(2, namespace);
statement2.setString(3, name);
Expand All @@ -171,7 +199,7 @@ public void delete(String resource) {
}
dbWriteLock.lock();
try (Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(REMOVE_ALL_PROPERTIES_STMT)) {
PreparedStatement statement = connection.prepareStatement(removeAllPropertiesStatement)) {
statement.setString(1, resource);
statement.execute();
} catch (SQLException e) {
Expand All @@ -190,7 +218,7 @@ public boolean propfind(String resource, Node property, boolean nameOnly, XMLWri
// Add the names of all properties
dbReadLock.lock();
try (Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(GET_PROPERTIES_NAMES_STMT)) {
PreparedStatement statement = connection.prepareStatement(getPropertiesNameStatement)) {
statement.setString(1, resource);
if (statement.execute()) {
ResultSet rs = statement.getResultSet();
Expand All @@ -209,7 +237,7 @@ public boolean propfind(String resource, Node property, boolean nameOnly, XMLWri
// Add a single property
dbReadLock.lock();
try (Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(GET_PROPERTY_STMT)) {
PreparedStatement statement = connection.prepareStatement(getPropertyStatement)) {
statement.setString(1, resource);
statement.setString(2, property.getNamespaceURI());
statement.setString(3, property.getLocalName());
Expand All @@ -230,7 +258,7 @@ public boolean propfind(String resource, Node property, boolean nameOnly, XMLWri
// Add all properties
dbReadLock.lock();
try (Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(GET_PROPERTIES_NODES_STMT)) {
PreparedStatement statement = connection.prepareStatement(getPropertiesNodeStatement)) {
statement.setString(1, resource);
if (statement.execute()) {
ResultSet rs = statement.getResultSet();
Expand Down Expand Up @@ -284,7 +312,7 @@ public void proppatch(String resource, ArrayList<ProppatchOperation> operations)
String serializedNode = strWriter.toString();
boolean found = false;
try {
try (PreparedStatement statement = connection.prepareStatement(GET_PROPERTY_STMT)) {
try (PreparedStatement statement = connection.prepareStatement(getPropertyStatement)) {
statement.setString(1, resource);
statement.setString(2, node.getNamespaceURI());
statement.setString(3, node.getLocalName());
Expand All @@ -296,15 +324,15 @@ public void proppatch(String resource, ArrayList<ProppatchOperation> operations)
}
}
if (found) {
try (PreparedStatement statement = connection.prepareStatement(SET_PROPERTY_STMT)) {
try (PreparedStatement statement = connection.prepareStatement(setPropertyStatement)) {
statement.setString(1, serializedNode);
statement.setString(2, resource);
statement.setString(3, node.getNamespaceURI());
statement.setString(4, node.getLocalName());
statement.execute();
}
} else {
try (PreparedStatement statement = connection.prepareStatement(ADD_PROPERTY_STMT)) {
try (PreparedStatement statement = connection.prepareStatement(addPropertyStatement)) {
statement.setString(1, resource);
statement.setString(2, node.getNamespaceURI());
statement.setString(3, node.getLocalName());
Expand All @@ -320,7 +348,7 @@ public void proppatch(String resource, ArrayList<ProppatchOperation> operations)
}
if (operation.getUpdateType() == PropertyUpdateType.REMOVE) {
Node node = operation.getPropertyNode();
try (PreparedStatement statement = connection.prepareStatement(REMOVE_PROPERTY_STMT)) {
try (PreparedStatement statement = connection.prepareStatement(removePropertyStatement)) {
statement.setString(1, resource);
statement.setString(2, node.getNamespaceURI());
statement.setString(3, node.getLocalName());
Expand Down
15 changes: 10 additions & 5 deletions test/org/apache/catalina/servlets/TestWebdavPropertyStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,12 @@ public class TestWebdavPropertyStore extends LoggingBaseTest {
"</V:someprop>";

public static final String SIMPLE_SCHEMA =
"create table properties (\n" +
" path varchar(256) not null,\n" +
" namespace varchar(64) not null,\n" +
" name varchar(64) not null,\n" +
" node varchar(1024) not null" +
"CREATE TABLE webdavproperties (\n" +
" path VARCHAR(1024) NOT NULL,\n" +
" namespace VARCHAR(64) NOT NULL,\n" +
" name VARCHAR(64) NOT NULL,\n" +
" node VARCHAR(2048) NOT NULL,\n" +
" PRIMARY KEY (path, namespace, name)\n" +
")";

public static class CustomDataSourcePropertyStore extends DataSourcePropertyStore {
Expand Down Expand Up @@ -176,7 +177,9 @@ public void testStore() throws Exception {
PropertyStore propertyStore = (PropertyStore) Class.forName(storeName).getDeclaredConstructor().newInstance();
if (propertyStore instanceof CustomDataSourcePropertyStore) {
((CustomDataSourcePropertyStore) propertyStore).setDataSource(new DerbyDataSource());
((CustomDataSourcePropertyStore) propertyStore).setTableName("webdavproperties");
}
propertyStore.init();

// Add properties
ArrayList<ProppatchOperation> operations = new ArrayList<>();
Expand Down Expand Up @@ -241,5 +244,7 @@ public void testStore() throws Exception {
Assert.assertFalse(propertyStore.propfind("/other/path2", node1, false, xmlWriter9));
Assert.assertTrue(xmlWriter9.toString().isEmpty());

propertyStore.destroy();

}
}
9 changes: 9 additions & 0 deletions webapps/docs/changelog.xml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,15 @@
issues do not "pop up" wrt. others).
-->
<section name="Tomcat 11.0.3 (markt)" rtext="in development">
<subsection name="Catalina">
<changelog>
<update>
Add <code>tableName</code> configuration on the
<code>DataSourcePropertyStore</code> that may be used by the WebDAV
Servlet. (remm)
</update>
</changelog>
</subsection>
</section>
<section name="Tomcat 11.0.2 (markt)" rtext="release in progress">
<subsection name="Catalina">
Expand Down

0 comments on commit 323071f

Please sign in to comment.