001: package sample.dms;
002:
003: import javax.sql.DataSource;
004:
005: import org.acegisecurity.Authentication;
006: import org.acegisecurity.GrantedAuthority;
007: import org.acegisecurity.GrantedAuthorityImpl;
008: import org.acegisecurity.context.SecurityContextHolder;
009: import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
010: import org.springframework.beans.factory.InitializingBean;
011: import org.springframework.jdbc.core.JdbcTemplate;
012: import org.springframework.transaction.PlatformTransactionManager;
013: import org.springframework.transaction.TransactionStatus;
014: import org.springframework.transaction.support.TransactionCallback;
015: import org.springframework.transaction.support.TransactionTemplate;
016: import org.springframework.util.Assert;
017:
018: /**
019: * Populates the DMS in-memory database with document and ACL information.
020: *
021: * @author Ben Alex
022: * @version $Id: DataSourcePopulator.java 1784 2007-02-24 21:00:24Z luke_t $
023: */
024: public class DataSourcePopulator implements InitializingBean {
025: protected static final int LEVEL_NEGATE_READ = 0;
026: protected static final int LEVEL_GRANT_READ = 1;
027: protected static final int LEVEL_GRANT_WRITE = 2;
028: protected static final int LEVEL_GRANT_ADMIN = 3;
029: protected JdbcTemplate template;
030: protected DocumentDao documentDao;
031: protected TransactionTemplate tt;
032:
033: public DataSourcePopulator(DataSource dataSource,
034: DocumentDao documentDao,
035: PlatformTransactionManager platformTransactionManager) {
036: Assert.notNull(dataSource, "DataSource required");
037: Assert.notNull(documentDao, "DocumentDao required");
038: Assert.notNull(platformTransactionManager,
039: "PlatformTransactionManager required");
040: this .template = new JdbcTemplate(dataSource);
041: this .documentDao = documentDao;
042: this .tt = new TransactionTemplate(platformTransactionManager);
043: }
044:
045: public void afterPropertiesSet() throws Exception {
046: // ACL tables
047: template
048: .execute("CREATE TABLE ACL_SID(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,PRINCIPAL BOOLEAN NOT NULL,SID VARCHAR_IGNORECASE(100) NOT NULL,CONSTRAINT UNIQUE_UK_1 UNIQUE(SID,PRINCIPAL));");
049: template
050: .execute("CREATE TABLE ACL_CLASS(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,CLASS VARCHAR_IGNORECASE(100) NOT NULL,CONSTRAINT UNIQUE_UK_2 UNIQUE(CLASS));");
051: template
052: .execute("CREATE TABLE ACL_OBJECT_IDENTITY(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,OBJECT_ID_CLASS BIGINT NOT NULL,OBJECT_ID_IDENTITY BIGINT NOT NULL,PARENT_OBJECT BIGINT,OWNER_SID BIGINT,ENTRIES_INHERITING BOOLEAN NOT NULL,CONSTRAINT UNIQUE_UK_3 UNIQUE(OBJECT_ID_CLASS,OBJECT_ID_IDENTITY),CONSTRAINT FOREIGN_FK_1 FOREIGN KEY(PARENT_OBJECT)REFERENCES ACL_OBJECT_IDENTITY(ID),CONSTRAINT FOREIGN_FK_2 FOREIGN KEY(OBJECT_ID_CLASS)REFERENCES ACL_CLASS(ID),CONSTRAINT FOREIGN_FK_3 FOREIGN KEY(OWNER_SID)REFERENCES ACL_SID(ID));");
053: template
054: .execute("CREATE TABLE ACL_ENTRY(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,ACL_OBJECT_IDENTITY BIGINT NOT NULL,ACE_ORDER INT NOT NULL,SID BIGINT NOT NULL,MASK INTEGER NOT NULL,GRANTING BOOLEAN NOT NULL,AUDIT_SUCCESS BOOLEAN NOT NULL,AUDIT_FAILURE BOOLEAN NOT NULL,CONSTRAINT UNIQUE_UK_4 UNIQUE(ACL_OBJECT_IDENTITY,ACE_ORDER),CONSTRAINT FOREIGN_FK_4 FOREIGN KEY(ACL_OBJECT_IDENTITY) REFERENCES ACL_OBJECT_IDENTITY(ID),CONSTRAINT FOREIGN_FK_5 FOREIGN KEY(SID) REFERENCES ACL_SID(ID));");
055:
056: // Normal authentication tables
057: template
058: .execute("CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(50) NOT NULL,ENABLED BOOLEAN NOT NULL);");
059: template
060: .execute("CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME));");
061: template
062: .execute("CREATE UNIQUE INDEX IX_AUTH_USERNAME ON AUTHORITIES(USERNAME,AUTHORITY);");
063:
064: // Document management system business tables
065: template
066: .execute("CREATE TABLE DIRECTORY(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, DIRECTORY_NAME VARCHAR_IGNORECASE(50) NOT NULL, PARENT_DIRECTORY_ID BIGINT)");
067: template
068: .execute("CREATE TABLE FILE(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY, FILE_NAME VARCHAR_IGNORECASE(50) NOT NULL, CONTENT VARCHAR_IGNORECASE(1024), PARENT_DIRECTORY_ID BIGINT)");
069:
070: // Populate the authentication and role tables
071: template
072: .execute("INSERT INTO USERS VALUES('marissa','a564de63c2d0da68cf47586ee05984d7',TRUE);");
073: template
074: .execute("INSERT INTO USERS VALUES('dianne','65d15fe9156f9c4bbffd98085992a44e',TRUE);");
075: template
076: .execute("INSERT INTO USERS VALUES('scott','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);");
077: template
078: .execute("INSERT INTO USERS VALUES('peter','22b5c9accc6e1ba628cedc63a72d57f8',FALSE);");
079: template
080: .execute("INSERT INTO USERS VALUES('bill','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);");
081: template
082: .execute("INSERT INTO USERS VALUES('bob','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);");
083: template
084: .execute("INSERT INTO USERS VALUES('jane','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);");
085: template
086: .execute("INSERT INTO AUTHORITIES VALUES('marissa','ROLE_USER');");
087: template
088: .execute("INSERT INTO AUTHORITIES VALUES('marissa','ROLE_SUPERVISOR');");
089: template
090: .execute("INSERT INTO AUTHORITIES VALUES('dianne','ROLE_USER');");
091: template
092: .execute("INSERT INTO AUTHORITIES VALUES('scott','ROLE_USER');");
093: template
094: .execute("INSERT INTO AUTHORITIES VALUES('peter','ROLE_USER');");
095: template
096: .execute("INSERT INTO AUTHORITIES VALUES('bill','ROLE_USER');");
097: template
098: .execute("INSERT INTO AUTHORITIES VALUES('bob','ROLE_USER');");
099: template
100: .execute("INSERT INTO AUTHORITIES VALUES('jane','ROLE_USER');");
101:
102: // Now create an ACL entry for the root directory
103: SecurityContextHolder
104: .getContext()
105: .setAuthentication(
106: new UsernamePasswordAuthenticationToken(
107: "marissa",
108: "ignored",
109: new GrantedAuthority[] { new GrantedAuthorityImpl(
110: "ROLE_IGNORED") }));
111: tt.execute(new TransactionCallback() {
112: public Object doInTransaction(TransactionStatus arg0) {
113: addPermission(documentDao, Directory.ROOT_DIRECTORY,
114: "ROLE_USER", LEVEL_GRANT_WRITE);
115: return null;
116: }
117: });
118:
119: // Now go off and create some directories and files for our users
120: createSampleData("marissa", "koala");
121: createSampleData("dianne", "emu");
122: createSampleData("scott", "wombat");
123: }
124:
125: /**
126: * Creates a directory for the user, and a series of sub-directories. The root directory is the parent for the user directory. The sub-directories
127: * are "confidential" and "shared". The ROLE_USER will be given read and write access to "shared".
128: */
129: private void createSampleData(String username, String password) {
130: Assert.notNull(documentDao, "DocumentDao required");
131: Assert.hasText(username, "Username required");
132:
133: Authentication auth = new UsernamePasswordAuthenticationToken(
134: username, password);
135:
136: try {
137: // Set the SecurityContextHolder ThreadLocal so any subclasses automatically know which user is operating
138: SecurityContextHolder.getContext().setAuthentication(auth);
139:
140: // Create the home directory first
141: Directory home = new Directory(username,
142: Directory.ROOT_DIRECTORY);
143: documentDao.create(home);
144: addPermission(documentDao, home, username,
145: LEVEL_GRANT_ADMIN);
146: addPermission(documentDao, home, "ROLE_USER",
147: LEVEL_GRANT_READ);
148: createFiles(documentDao, home);
149:
150: // Now create the confidential directory
151: Directory confid = new Directory("confidential", home);
152: documentDao.create(confid);
153: addPermission(documentDao, confid, "ROLE_USER",
154: LEVEL_NEGATE_READ);
155: createFiles(documentDao, confid);
156:
157: // Now create the shared directory
158: Directory shared = new Directory("shared", home);
159: documentDao.create(shared);
160: addPermission(documentDao, shared, "ROLE_USER",
161: LEVEL_GRANT_READ);
162: addPermission(documentDao, shared, "ROLE_USER",
163: LEVEL_GRANT_WRITE);
164: createFiles(documentDao, shared);
165: } finally {
166: // Clear the SecurityContextHolder ThreadLocal so future calls are guaranteed to be clean
167: SecurityContextHolder.clearContext();
168: }
169: }
170:
171: private void createFiles(DocumentDao documentDao, Directory parent) {
172: Assert.notNull(documentDao, "DocumentDao required");
173: Assert.notNull(parent, "Parent required");
174: int countBeforeInsert = documentDao.findElements(parent).length;
175: for (int i = 0; i < 10; i++) {
176: File file = new File("file_" + i + ".txt", parent);
177: documentDao.create(file);
178: }
179: Assert.isTrue(countBeforeInsert + 10 == documentDao
180: .findElements(parent).length,
181: "Failed to increase count by 10");
182: }
183:
184: /**
185: * Allows subclass to add permissions.
186: *
187: * @param documentDao that will presumably offer methods to enable the operation to be completed
188: * @param element to the subject of the new permissions
189: * @param recipient to receive permission (if it starts with ROLE_ it is assumed to be a GrantedAuthority, else it is a username)
190: * @param level based on the static final integer fields on this class
191: */
192: protected void addPermission(DocumentDao documentDao,
193: AbstractElement element, String recipient, int level) {
194: }
195: }
|