diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java b/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java
index 44ff55ce80..1a505f8c45 100644
--- a/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java
+++ b/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java
@@ -64,11 +64,47 @@ import org.springframework.util.Assert;
* you are likely to achieve better performance. In such situations you will need to provide your own custom
* LookupStrategy. This class does not support subclassing, as it is likely to change in future releases
* and therefore subclassing is unsupported.
+ *
+ * There are two SQL queries executed, one in the lookupPrimaryKeys method and one in
+ * lookupObjectIdentities. These are built from the same select and "order by" clause, using a different
+ * where clause in each case. In order to use custom schema or column names, each of these SQL clauses can be
+ * customized, but they must be consistent with each other and with the expected result set
+ * generated by the the default values.
*
* @author Ben Alex
* @version $Id$
*/
public final class BasicLookupStrategy implements LookupStrategy {
+
+ public final static String DEFAULT_SELECT_CLAUSE = "select acl_object_identity.object_id_identity, "
+ + "acl_entry.ace_order, "
+ + "acl_object_identity.id as acl_id, "
+ + "acl_object_identity.parent_object, "
+ + "acl_object_identity.entries_inheriting, "
+ + "acl_entry.id as ace_id, "
+ + "acl_entry.mask, "
+ + "acl_entry.granting, "
+ + "acl_entry.audit_success, "
+ + "acl_entry.audit_failure, "
+ + "acl_sid.principal as ace_principal, "
+ + "acl_sid.sid as ace_sid, "
+ + "acli_sid.principal as acl_principal, "
+ + "acli_sid.sid as acl_sid, "
+ + "acl_class.class "
+ + "from acl_object_identity "
+ + "left join acl_sid acli_sid on acli_sid.id = acl_object_identity.owner_sid "
+ + "left join acl_class on acl_class.id = acl_object_identity.object_id_class "
+ + "left join acl_entry on acl_object_identity.id = acl_entry.acl_object_identity "
+ + "left join acl_sid on acl_entry.sid = acl_sid.id "
+ + "where ( ";
+
+ private final static String DEFAULT_LOOKUP_KEYS_WHERE_CLAUSE = "(acl_object_identity.id = ?)";
+
+ private final static String DEFAULT_LOOKUP_IDENTITIES_WHERE_CLAUSE = "(acl_object_identity.object_id_identity = ? and acl_class.class = ?)";
+
+ public final static String DEFAULT_ORDER_BY_CLAUSE = ") order by acl_object_identity.object_id_identity"
+ + " asc, acl_entry.ace_order asc";
+
//~ Instance fields ================================================================================================
private AclAuthorizationStrategy aclAuthorizationStrategy;
@@ -81,6 +117,12 @@ public final class BasicLookupStrategy implements LookupStrategy {
private final Field fieldAces = FieldUtils.getField(AclImpl.class, "aces");
private final Field fieldAcl = FieldUtils.getField(AccessControlEntryImpl.class, "acl");
+ // SQL Customization fields
+ private String selectClause = DEFAULT_SELECT_CLAUSE;
+ private String lookupPrimaryKeysWhereClause = DEFAULT_LOOKUP_KEYS_WHERE_CLAUSE;
+ private String lookupObjectIdentitiesWhereClause = DEFAULT_LOOKUP_IDENTITIES_WHERE_CLAUSE;
+ private String orderByClause = DEFAULT_ORDER_BY_CLAUSE;
+
//~ Constructors ===================================================================================================
/**
@@ -106,33 +148,12 @@ public final class BasicLookupStrategy implements LookupStrategy {
//~ Methods ========================================================================================================
- private static String computeRepeatingSql(String repeatingSql, int requiredRepetitions) {
+ private String computeRepeatingSql(String repeatingSql, int requiredRepetitions) {
assert requiredRepetitions > 0 : "requiredRepetitions must be > 0";
- final String startSql = "select acl_object_identity.object_id_identity, "
- + "acl_entry.ace_order, "
- + "acl_object_identity.id as acl_id, "
- + "acl_object_identity.parent_object, "
- + "acl_object_identity.entries_inheriting, "
- + "acl_entry.id as ace_id, "
- + "acl_entry.mask, "
- + "acl_entry.granting, "
- + "acl_entry.audit_success, "
- + "acl_entry.audit_failure, "
- + "acl_sid.principal as ace_principal, "
- + "acl_sid.sid as ace_sid, "
- + "acli_sid.principal as acl_principal, "
- + "acli_sid.sid as acl_sid, "
- + "acl_class.class "
- + "from acl_object_identity "
- + "left join acl_sid acli_sid on acli_sid.id = acl_object_identity.owner_sid "
- + "left join acl_class on acl_class.id = acl_object_identity.object_id_class "
- + "left join acl_entry on acl_object_identity.id = acl_entry.acl_object_identity "
- + "left join acl_sid on acl_entry.sid = acl_sid.id "
- + "where ( ";
+ final String startSql = selectClause;
- final String endSql = ") order by acl_object_identity.object_id_identity"
- + " asc, acl_entry.ace_order asc";
+ final String endSql = orderByClause;
StringBuilder sqlStringBldr =
new StringBuilder(startSql.length() + endSql.length() + requiredRepetitions * (repeatingSql.length() + 4));
@@ -239,7 +260,7 @@ public final class BasicLookupStrategy implements LookupStrategy {
Assert.notNull(acls, "ACLs are required");
Assert.notEmpty(findNow, "Items to find now required");
- String sql = computeRepeatingSql("(acl_object_identity.id = ?)", findNow.size());
+ String sql = computeRepeatingSql(lookupPrimaryKeysWhereClause, findNow.size());
Set
* The default settings are for HSQLDB. If you are using a different database you
* will probably need to set the {@link #setSidIdentityQuery(String) sidIdentityQuery} and
- * {@link #setClassIdentityQuery(String) classIdentityQuery} properties appropriately.
+ * {@link #setClassIdentityQuery(String) classIdentityQuery} properties appropriately. The other queries,
+ * SQL inserts and updates can also be customized to accomodate schema variations, but must produce results
+ * consistent with those expected by the defaults.
*
* See the appendix of the Spring Security reference manual for more information on the expected schema
* and how it is used. Information on using PostgreSQL is also included.
@@ -383,6 +385,47 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS
Assert.hasText(sidIdentityQuery, "New sidIdentityQuery query is required");
this.sidIdentityQuery = sidIdentityQuery;
}
+
+ public void setDeleteEntryByObjectIdentityForeignKeySql(String deleteEntryByObjectIdentityForeignKey) {
+ this.deleteEntryByObjectIdentityForeignKey = deleteEntryByObjectIdentityForeignKey;
+ }
+
+ public void setDeleteObjectIdentityByPrimaryKeySql(String deleteObjectIdentityByPrimaryKey) {
+ this.deleteObjectIdentityByPrimaryKey = deleteObjectIdentityByPrimaryKey;
+ }
+
+ public void setInsertClassSql(String insertClass) {
+ this.insertClass = insertClass;
+ }
+
+ public void setInsertEntrySql(String insertEntry) {
+ this.insertEntry = insertEntry;
+ }
+
+ public void setInsertObjectIdentitySql(String insertObjectIdentity) {
+ this.insertObjectIdentity = insertObjectIdentity;
+ }
+
+ public void setInsertSidSql(String insertSid) {
+ this.insertSid = insertSid;
+ }
+
+ public void setClassPrimaryKeyQuery(String selectClassPrimaryKey) {
+ this.selectClassPrimaryKey = selectClassPrimaryKey;
+ }
+
+ public void setObjectIdentityPrimaryKeyQuery(String selectObjectIdentityPrimaryKey) {
+ this.selectObjectIdentityPrimaryKey = selectObjectIdentityPrimaryKey;
+ }
+
+ public void setSidPrimaryKeyQuery(String selectSidPrimaryKey) {
+ this.selectSidPrimaryKey = selectSidPrimaryKey;
+ }
+
+ public void setUpdateObjectIdentity(String updateObjectIdentity) {
+ this.updateObjectIdentity = updateObjectIdentity;
+ }
+
/**
* @param foreignKeysInDatabase if false this class will perform additional FK constrain checking, which may
* cause deadlocks (the default is true, so deadlocks are avoided but the database is expected to enforce FKs)