I've developed an extension for Spring Security 2.0.4 that introduces off-the-shelf support for loading a RoleHierarchy from a database.
I hereby release this to the Spring community under the terms of the latest GNU GPL at the time of posting.
Here is the subclass of RoleHierarchyImpl, called RoleHierarchyImplDaoAware:
Here is the interface for RoleHierarchyEntry:Code:package org.springframework.security.userdetails.hierarchicalroles; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import javax.sql.DataSource; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.jdbc.object.MappingSqlQuery; /** * A DAO for retrieving role hierarchies from a SQL database using JDBC. * The default SQL string for _findAllRoleHierarchyEntriesQuery is "select * from role_hierarchies", with columns named "includingRole" * and "includedRole." Users of this Dao may use property injection to change the default SQL string * @author acanon * */ public class RoleHierarchyEntryDaoJdbc extends JdbcDaoSupport implements RoleHierarchyEntryDao { private String _findAllRoleHierarchyEntriesQuery = "select * from role_hierarchies"; public String get_findAllRoleHierarchyEntriesQuery() { return _findAllRoleHierarchyEntriesQuery; } public void set_findAllRoleHierarchyEntriesQuery( String allRoleHierarchyEntriesQuery) { _findAllRoleHierarchyEntriesQuery = allRoleHierarchyEntriesQuery; } private FindAllRoleHierarchyEntriesMapping _findAllRoleHierarchyEntriesMapping; protected void initDao() { _findAllRoleHierarchyEntriesMapping = new FindAllRoleHierarchyEntriesMapping(this.getDataSource()); } protected class FindAllRoleHierarchyEntriesMapping extends MappingSqlQuery { protected FindAllRoleHierarchyEntriesMapping(DataSource ds) { super(ds, _findAllRoleHierarchyEntriesQuery); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { return new RoleHierarchyEntryImpl(rs.getString("includingRole"),rs.getString("includedRole")); } } @SuppressWarnings("unchecked") public List<RoleHierarchyEntry> findAll() { return (List<RoleHierarchyEntry>) this._findAllRoleHierarchyEntriesMapping.execute(); } }
And a minimal implementation, which produces "ROLE1 > ROLE2" type strings suitable for RoleHierarchyImpl:Code:package org.springframework.security.userdetails.hierarchicalroles; /** * RoleHierarchyEntry is an interface for representing a simple inclusion relationship between hierarchical roles. * Potential implementors of this interface include DAOs which retrieve hierarchical roles from a database as * a list of rules of the form "Role A includes Role B." * * A useful implementation is found in RoleHierarchyEntryImpl, which overrides the toString() method to return a textual * representation of role hierarchy entry suitable for passing to the setHierarchy() method of the RoleHierarchyImpl class * of Spring Security 2.0.4. * * @author Alan B. Canon */ public interface RoleHierarchyEntry { /** * Gets the string that is the name of the including role, indicating that this role includes the "included" * role of this RoleHierarchyEntry. * @return the including role. */ public abstract String getIncludingRole(); /** * Sets the string that is the name of the including role, indicating that this role includes the "included" * role of this RoleHierarchyEntry. * @param includingRole */ public abstract void setIncludingRole(String includingRole); /** * Gets the string that is the name of the included role, indicating that this role is included by the "including" * role of this RoleHierarchyEntry. * @return the included role. */ public abstract String getIncludedRole(); /** * Sets the string that is the name of the included role, indicating that this role is included by the "including" * role of this RoleHierarchyEntry. * @param includedRole */ public abstract void setIncludedRole(String includedRole); }
Here is the contract for the DAO:Code:package org.springframework.security.userdetails.hierarchicalroles; /** * Minimal implementation of RoleHierarchyEntry that can return a string representation suitable for input to the * setHierarchy() method of RoleHierarchyImpl. * @author Alan B. Canon */ public class RoleHierarchyEntryImpl implements RoleHierarchyEntry { /** * Constructs a RoleHierarchyEntryImpl with an including and an included role. */ RoleHierarchyEntryImpl(String includingRole, String includedRole) { this.setIncludingRole(includingRole); this.setIncludedRole(includedRole); } private String includingRole = null; /** * Gets the string that is the name of the including role, indicating that this role includes the "included" role of this * RoleHierarchyEntry. * @see org.springframework.security.userdetails.hierarchicalroles.RoleHierarchyEntry#getIncludingRole() */ public String getIncludingRole() { return includingRole; } /** * Sets the string that is the name of the including role, indicating that this role includes the "included" role of this * RoleHierarchyEntry. * @see org.springframework.security.userdetails.hierarchicalroles.RoleHierarchyEntry#setIncludingRole(java.lang.String) */ public void setIncludingRole(String includingRole) { this.includingRole = includingRole; } /** * Gets the string that is the name of the included role, indicating that this role is included by the "including" * role of this RoleHierarchyEntry. * @see org.springframework.security.userdetails.hierarchicalroles.RoleHierarchyEntry#getIncludedRole() */ public String getIncludedRole() { return includedRole; } /** * Sets the string that is the name of the included role, indicating that this role is included by the "including" * role of this RoleHierarchyEntry. * @see org.springframework.security.userdetails.hierarchicalroles.RoleHierarchyEntry#setIncludedRole(java.lang.String) */ public void setIncludedRole(String includedRole) { this.includedRole = includedRole; } private String includedRole = null; @Override public String toString() { return includingRole + " > " + includedRole + "\n"; } }
And here is a JDBC implementation of that DAO:Code:package org.springframework.security.userdetails.hierarchicalroles; import java.util.List; /** * DAO object for RoleHierarchyEntry. * @author acanon * */ public interface RoleHierarchyEntryDao { public List<RoleHierarchyEntry> findAll(); }
I haven't done a full test of it, but you get the idea.Code:package org.springframework.security.userdetails.hierarchicalroles; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import javax.sql.DataSource; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.jdbc.object.MappingSqlQuery; /** * A DAO for retrieving role hierarchies from a SQL database using JDBC. * The default SQL string for _findAllRoleHierarchyEntriesQuery is "select * from role_hierarchies", with columns named "includingRole" * and "includedRole." Users of this Dao may use property injection to change the default SQL string * @author Alan B. Canon * */ public class RoleHierarchyEntryDaoJdbc extends JdbcDaoSupport implements RoleHierarchyEntryDao { private String _findAllRoleHierarchyEntriesQuery = "select * from role_hierarchies"; public String get_findAllRoleHierarchyEntriesQuery() { return _findAllRoleHierarchyEntriesQuery; } public void set_findAllRoleHierarchyEntriesQuery( String allRoleHierarchyEntriesQuery) { _findAllRoleHierarchyEntriesQuery = allRoleHierarchyEntriesQuery; } private FindAllRoleHierarchyEntriesMapping _findAllRoleHierarchyEntriesMapping; protected void initDao() { _findAllRoleHierarchyEntriesMapping = new FindAllRoleHierarchyEntriesMapping(this.getDataSource()); } protected class FindAllRoleHierarchyEntriesMapping extends MappingSqlQuery { protected FindAllRoleHierarchyEntriesMapping(DataSource ds) { super(ds, _findAllRoleHierarchyEntriesQuery); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { return new RoleHierarchyEntryImpl(rs.getString("includingRole"),rs.getString("includedRole")); } } @SuppressWarnings("unchecked") public List<RoleHierarchyEntry> findAll() { return (List<RoleHierarchyEntry>) this._findAllRoleHierarchyEntriesMapping.execute(); } }


