]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
674f750535fde8780b9fb02577ccef2a136202a6
[tmp/jakarta-migration.git] /
1 package org.collectionspace.services.common.authorization_mgt;
2
3 import java.sql.Connection;
4 import java.sql.PreparedStatement;
5 import java.sql.ResultSet;
6 import java.sql.SQLException;
7 import java.sql.Statement;
8 import java.util.ArrayList;
9 import java.util.Date;
10 import java.util.HashMap;
11 import java.util.Hashtable;
12 import java.util.List;
13 import java.util.UUID;
14
15 import javax.naming.NamingException;
16 import javax.persistence.EntityManager;
17 import javax.persistence.EntityManagerFactory;
18
19 import org.collectionspace.authentication.AuthN;
20 import org.collectionspace.services.authorization.AuthZ;
21 import org.collectionspace.services.authorization.CSpaceAction;
22 import org.collectionspace.services.authorization.PermissionException;
23 import org.collectionspace.services.authorization.PermissionRole;
24 import org.collectionspace.services.authorization.PermissionRoleRel;
25 import org.collectionspace.services.authorization.PermissionValue;
26 import org.collectionspace.services.authorization.Role;
27 import org.collectionspace.services.authorization.RoleValue;
28 import org.collectionspace.services.authorization.SubjectType;
29 import org.collectionspace.services.authorization.URIResourceImpl;
30 import org.collectionspace.services.authorization.perms.ActionType;
31 import org.collectionspace.services.authorization.perms.EffectType;
32 import org.collectionspace.services.authorization.perms.Permission;
33 import org.collectionspace.services.authorization.perms.PermissionAction;
34
35 import org.collectionspace.services.client.Profiler;
36 import org.collectionspace.services.client.RoleClient;
37 import org.collectionspace.services.client.workflow.WorkflowClient;
38 import org.collectionspace.services.common.config.ServiceConfigUtils;
39 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
40 import org.collectionspace.services.common.context.ServiceBindingUtils;
41 import org.collectionspace.services.common.document.DocumentHandler;
42 import org.collectionspace.services.common.security.SecurityUtils;
43 import org.collectionspace.services.common.storage.DatabaseProductType;
44 import org.collectionspace.services.common.storage.JDBCTools;
45 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
46 import org.collectionspace.services.config.service.ServiceBindingType;
47 import org.collectionspace.services.config.tenant.TenantBindingType;
48
49 import org.collectionspace.services.lifecycle.Lifecycle;
50 import org.collectionspace.services.lifecycle.TransitionDef;
51 import org.collectionspace.services.lifecycle.TransitionDefList;
52
53 //import org.mortbay.log.Log;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57 import org.springframework.security.acls.model.AlreadyExistsException;
58
59
60 public class AuthorizationCommon {
61         
62         final public static String REFRESH_AUTZ_PROP = "refreshAuthZOnStartup";
63     //
64     // ActionGroup labels/constants
65     //
66         
67         // for READ-WRITE
68     final public static String ACTIONGROUP_CRUDL_NAME = "CRUDL";
69     final public static ActionType[] ACTIONSET_CRUDL = {ActionType.CREATE, ActionType.READ, ActionType.UPDATE, ActionType.DELETE, ActionType.SEARCH};
70     // for READ-ONLY
71     final public static String ACTIONGROUP_RL_NAME = "RL";
72     final public static ActionType[] ACTIONSET_RL = {ActionType.READ, ActionType.SEARCH};
73
74     
75         /*
76          * Inner class to deal with predefined ADMIN and READER action groupds
77          */
78         public class ActionGroup {
79                 String name;
80                 ActionType[] actions;
81         }
82         
83         static ActionGroup ACTIONGROUP_CRUDL;
84         static ActionGroup ACTIONGROUP_RL;
85         
86         // A static block to initialize the predefined action groups
87         static {
88                 AuthorizationCommon ac = new AuthorizationCommon();
89                 // For admin
90                 ACTIONGROUP_CRUDL = ac.new ActionGroup();
91                 ACTIONGROUP_CRUDL.name = ACTIONGROUP_CRUDL_NAME;
92                 ACTIONGROUP_CRUDL.actions = ACTIONSET_CRUDL;
93                 // For reader
94                 ACTIONGROUP_RL = ac.new ActionGroup();
95                 ACTIONGROUP_RL.name = ACTIONGROUP_RL_NAME;
96                 ACTIONGROUP_RL.actions = ACTIONSET_RL;
97
98         }
99         
100     final static Logger logger = LoggerFactory.getLogger(AuthorizationCommon.class);
101
102     //
103     // The "super" role has a predefined ID of "0" and a tenant ID of "0";
104     //
105     final public static String ROLE_ALL_TENANTS_MANAGER = "ALL_TENANTS_MANAGER";
106     final public static String ROLE_ALL_TENANTS_MANAGER_ID = "0";
107     final public static String ALL_TENANTS_MANAGER_TENANT_ID = "0";
108
109     final public static String ROLE_TENANT_ADMINISTRATOR = "TENANT_ADMINISTRATOR";
110     final public static String ROLE_TENANT_READER = "TENANT_READER";
111         
112     public static final String TENANT_MANAGER_USER = "tenantManager"; 
113     public static final String TENANT_MANAGER_SCREEN_NAME = TENANT_MANAGER_USER; 
114     public static final String DEFAULT_TENANT_MANAGER_PASSWORD = "manage"; 
115     public static final String DEFAULT_TENANT_MANAGER_EMAIL = "tenantManager@collectionspace.org"; 
116     
117     public static final String TENANT_ADMIN_ACCT_PREFIX = "admin@"; 
118     public static final String TENANT_READER_ACCT_PREFIX = "reader@"; 
119     public static final String ROLE_PREFIX = "ROLE_"; 
120     public static final String SPRING_ADMIN_ROLE = "ROLE_SPRING_ADMIN"; 
121     public static final String TENANT_ADMIN_ROLE_SUFFIX = "_TENANT_ADMINISTRATOR"; 
122     public static final String TENANT_READER_ROLE_SUFFIX = "_TENANT_READER"; 
123     public static final String DEFAULT_ADMIN_PASSWORD = "Administrator";
124     public static final String DEFAULT_READER_PASSWORD = "reader";
125
126     public static final String ROLE_SPRING_ADMIN_ID = "-1";
127     public static final String ROLE_SPRING_ADMIN_NAME = "ROLE_SPRING_ADMIN";
128     
129     // SQL for init tasks
130         final private static String INSERT_ACCOUNT_ROLE_SQL_MYSQL = 
131                         "INSERT INTO accounts_roles(account_id, user_id, role_id, role_name, created_at)"
132                                         +" VALUES(?, ?, ?, ?, now())";
133         final private static String INSERT_ACCOUNT_ROLE_SQL_POSTGRES =
134                         "INSERT INTO accounts_roles(HJID, account_id, user_id, role_id, role_name, created_at)"
135                                         +" VALUES(nextval('hibernate_sequence'), ?, ?, ?, ?, now())";
136         final private static String QUERY_USERS_SQL = 
137                 "SELECT username FROM users WHERE username LIKE '"
138                         +TENANT_ADMIN_ACCT_PREFIX+"%' OR username LIKE '"+TENANT_READER_ACCT_PREFIX+"%'";
139         final private static String INSERT_USER_SQL = 
140                         "INSERT INTO users (username,passwd, created_at) VALUES (?,?, now())";
141         final private static String INSERT_ACCOUNT_SQL = 
142                         "INSERT INTO accounts_common "
143                                         + "(csid, email, userid, status, screen_name, metadata_protection, roles_protection, created_at) "
144                                         + "VALUES (?,?,?,'ACTIVE',?, 'immutable', 'immutable', now())";
145         
146         // TENANT MANAGER specific SQL
147         final private static String QUERY_TENANT_MGR_USER_SQL = 
148                 "SELECT username FROM users WHERE username = '"+TENANT_MANAGER_USER+"'";
149         final private static String GET_TENANT_MGR_ROLE_SQL =
150                         "SELECT csid from roles WHERE tenant_id='"+ALL_TENANTS_MANAGER_TENANT_ID+"' and rolename=?";
151
152     public static Role getRole(String tenantId, String displayName) {
153         Role role = null;
154         
155         String roleName = AuthorizationCommon.getQualifiedRoleName(tenantId, displayName);
156         role = AuthorizationStore.getRoleByName(roleName, tenantId);
157         
158         return role;
159     }
160     
161     public static Role getRole(EntityManager em, String tenantId, String displayName) {
162         Role role = null;
163         
164         String roleName = AuthorizationCommon.getQualifiedRoleName(tenantId, displayName);
165         role = AuthorizationStore.getRoleByName(em, roleName, tenantId);
166         
167         return role;
168     }
169     
170     
171     public static Role createRole(String tenantId, String name, String description) {
172         return createRole(tenantId, name, description, false /* mutable by default */);
173     }
174     
175     public static Role createRole(String tenantId, String name, String description, boolean immutable) {
176         Role role = new Role();
177         
178         role.setCreatedAtItem(new Date());
179         role.setDisplayName(name);
180         String roleName = AuthorizationCommon.getQualifiedRoleName(tenantId, name);     
181         role.setRoleName(roleName);
182         String id = UUID.randomUUID().toString(); //FIXME: The qualified role name should be unique enough to use as an ID/key
183         role.setCsid(id);
184                 role.setDescription(description);
185         role.setTenantId(tenantId);
186         if (immutable == true) {
187                 role.setMetadataProtection(RoleClient.IMMUTABLE);
188                 role.setPermsProtection(RoleClient.IMMUTABLE);
189         }
190         
191         return role;
192     }
193     
194     /**
195      * Add permission to the Spring Security tables
196      * with assumption that resource is of type URI
197      * @param permission configuration
198      */
199     public static void addPermissionsForUri(Permission perm,
200             PermissionRole permRole) throws PermissionException {
201         //
202         // First check the integrity of the incoming arguments.
203         //
204         if (!perm.getCsid().equals(permRole.getPermission().get(0).getPermissionId())) {
205             throw new IllegalArgumentException("permission ids do not"
206                     + " match for role=" + permRole.getRole().get(0).getRoleName()
207                     + " with permissionId=" + permRole.getPermission().get(0).getPermissionId()
208                     + " for permission with csid=" + perm.getCsid());
209         }
210         
211         List<String> principals = new ArrayList<String>();        
212         for (RoleValue roleValue : permRole.getRole()) {
213             principals.add(roleValue.getRoleName());
214         }
215         List<PermissionAction> permActions = perm.getAction();
216         for (PermissionAction permAction : permActions) {
217                 try {
218                     CSpaceAction action = URIResourceImpl.getAction(permAction.getName()); 
219                     URIResourceImpl uriRes = new URIResourceImpl(perm.getTenantId(),
220                             perm.getResourceName(), action);
221                     boolean grant = perm.getEffect().equals(EffectType.PERMIT) ? true : false;
222                     AuthZ.get().addPermissions(uriRes, principals.toArray(new String[0]), grant);//CSPACE-4967
223                 } catch (PermissionException e) {
224                         //
225                         // Only throw the exception if it is *not* an already-exists exception
226                         //
227                         if (e.getCause() instanceof AlreadyExistsException == false) {
228                                 throw e;
229                         }
230                 }
231         }
232     }
233     
234     private static Connection getConnection(String databaseName) throws NamingException, SQLException {
235         return JDBCTools.getConnection(JDBCTools.CSPACE_DATASOURCE_NAME,
236                         databaseName);
237     }
238     
239     /*
240      * Spring security seems to require that all of our role names start
241      * with the ROLE_PREFIX string.
242      */
243     public static String getQualifiedRoleName(String tenantId, String name) {
244         String result = name;
245         
246         String qualifiedName = ROLE_PREFIX + tenantId.toUpperCase() + "_" + name.toUpperCase();         
247         if (name.equals(qualifiedName) == false) {
248                 result = qualifiedName;
249         }
250         
251         return result;
252     }
253         
254     private static ActionGroup getActionGroup(String actionGroupStr) {
255         ActionGroup result = null;
256         
257         if (actionGroupStr.equalsIgnoreCase(ACTIONGROUP_CRUDL_NAME)) {
258                 result = ACTIONGROUP_CRUDL;
259         } else if (actionGroupStr.equalsIgnoreCase(ACTIONGROUP_RL_NAME)) {
260                 result = ACTIONGROUP_RL;
261         }
262         
263         return result;
264     }
265     
266     public static Permission createPermission(String tenantId,
267                 String resourceName,
268                 String description,
269                 String actionGroupStr) {
270         Permission result = null;
271         
272         ActionGroup actionGroup = getActionGroup(actionGroupStr);
273         result = createPermission(tenantId, resourceName, description, actionGroup);
274         
275         return result;
276     }
277     
278     private static Permission createPermission(String tenantId,
279                 String resourceName,
280                 String description,
281                 ActionGroup actionGroup) {
282         String id = tenantId
283                         + "-" + resourceName.replace('/', '_') // Remove the slashes so the ID can be used in a URI/URL
284                         + "-" + actionGroup.name;
285         Permission perm = new Permission();
286         perm.setCsid(id);
287         perm.setDescription(description);
288         perm.setCreatedAtItem(new Date());
289         perm.setResourceName(resourceName.toLowerCase().trim());
290         perm.setEffect(EffectType.PERMIT);
291         perm.setTenantId(tenantId);
292         
293         perm.setActionGroup(actionGroup.name);
294         ArrayList<PermissionAction> pas = new ArrayList<PermissionAction>();
295         perm.setAction(pas);
296         for (ActionType actionType : actionGroup.actions) {
297                 PermissionAction permAction = createPermissionAction(perm, actionType);
298                 pas.add(permAction);
299         }
300         
301         return perm;
302     }
303     
304     private static Permission createWorkflowPermission(TenantBindingType tenantBinding,
305                 ServiceBindingType serviceBinding,
306                 TransitionDef transitionDef,
307                 ActionGroup actionGroup)
308     {
309         Permission result = null;
310         String workFlowServiceSuffix;
311         String transitionName;
312         if (transitionDef != null) {
313                 transitionName = transitionDef.getName();
314                 workFlowServiceSuffix = WorkflowClient.SERVICE_AUTHZ_SUFFIX;
315         } else {
316                 transitionName = ""; //since the transitionDef was null, we're assuming that this is the base workflow permission to be created                 
317                 workFlowServiceSuffix = WorkflowClient.SERVICE_PATH;
318         }
319         
320         String tenantId = tenantBinding.getId();
321         String resourceName = "/"
322                         + serviceBinding.getName().toLowerCase().trim()
323                         + workFlowServiceSuffix
324                         + transitionName;
325         String description = "A generated workflow permission for actiongroup " + actionGroup.name;
326         result = createPermission(tenantId, resourceName, description, actionGroup);
327         
328         if (logger.isDebugEnabled() == true) {
329                 logger.debug("Generated a workflow permission: "
330                                 + result.getResourceName()
331                                 + ":" + transitionName
332                                 + ":" + "tenant id=" + result.getTenantId()
333                                 + ":" + actionGroup.name);
334         }
335         
336         return result;
337     }
338     
339     private static PermissionRole createPermissionRole(EntityManager em,
340                 Permission permission,
341                 Role role,
342                 boolean enforceTenancy) throws Exception
343     {
344         PermissionRole permRole = new PermissionRole();
345         // Check to see if the tenant ID of the permission and the tenant ID of the role match
346         boolean tenantIdsMatch = role.getTenantId().equalsIgnoreCase(permission.getTenantId());
347         if (tenantIdsMatch == false && enforceTenancy == false) {
348                 tenantIdsMatch = true; // If we don't need to enforce tenancy then we'll just consider them matched.
349         }
350                         
351                 if (tenantIdsMatch == true) {
352                 permRole.setSubject(SubjectType.ROLE);
353                 //
354                 // Set of the permission value list of the permrole
355                 //
356                 List<PermissionValue> permValues = new ArrayList<PermissionValue>();
357                 PermissionValue permValue = new PermissionValue();
358                 permValue.setPermissionId(permission.getCsid());
359                 permValue.setResourceName(permission.getResourceName().toLowerCase());
360                 permValue.setActionGroup(permission.getActionGroup());
361                 permValues.add(permValue);
362                 permRole.setPermission(permValues);
363                 //
364                 // Set of the role value list of the permrole
365                 //
366                 List<RoleValue> roleValues = new ArrayList<RoleValue>();
367                 RoleValue rv = new RoleValue();
368             // This needs to use the qualified name, not the display name
369             rv.setRoleName(role.getRoleName());
370             rv.setRoleId(role.getCsid());
371             roleValues.add(rv);
372             permRole.setRole(roleValues);
373                 } else {
374                 String errMsg = "The tenant ID of the role: " + role.getTenantId()
375                                 + " did not match the tenant ID of the permission: " + permission.getTenantId();
376                 throw new Exception(errMsg);
377                 }
378         
379         return permRole;
380     }
381     
382     private static Hashtable<String, String> getTenantNamesFromConfig(TenantBindingConfigReaderImpl tenantBindingConfigReader) {
383
384         // Note that this only handles tenants not marked as "createDisabled"
385         Hashtable<String, TenantBindingType> tenantBindings =
386                         tenantBindingConfigReader.getTenantBindings();
387         Hashtable<String, String> tenantInfo = new Hashtable<String, String>();
388         for (TenantBindingType tenantBinding : tenantBindings.values()) {
389                 String tId = tenantBinding.getId();
390                 String tName = tenantBinding.getName();
391                 tenantInfo.put(tId, tName);
392                 if (logger.isDebugEnabled()) {
393                         logger.debug("getTenantNamesFromConfig found configured tenant id: "+tId+" name: "+tName);
394                 }
395         }
396         return tenantInfo;
397     }
398     
399     private static ArrayList<String> compileExistingTenants(Connection conn, Hashtable<String, String> tenantInfo)
400         throws SQLException, Exception {
401         Statement stmt = null;
402         ArrayList<String> existingTenants = new ArrayList<String>();
403         // First find or create the tenants
404         final String queryTenantSQL = "SELECT id,name FROM tenants";
405         try {
406                 stmt = conn.createStatement();
407                 ResultSet rs = stmt.executeQuery(queryTenantSQL);
408                 while (rs.next()) {
409                         String tId = rs.getString("id");
410                         String tName = rs.getString("name");
411                         if(tenantInfo.containsKey(tId)) {
412                                 existingTenants.add(tId);
413                                 if(!tenantInfo.get(tId).equalsIgnoreCase(tName)) {
414                                         logger.warn("Configured name for tenant: "
415                                                         +tId+" in repository: "+tName
416                                                         +" does not match config'd name: "+ tenantInfo.get(tId));
417                                 }
418                         }
419                 }
420                 rs.close();
421         } catch(Exception e) {
422                 throw e;
423         } finally {
424                 if(stmt!=null)
425                         stmt.close();
426         }
427
428         return existingTenants;
429     }
430     
431     private static void createMissingTenants(Connection conn, Hashtable<String, String> tenantInfo,
432                 ArrayList<String> existingTenants) throws SQLException, Exception {
433                 // Need to define and look for a createDisabled attribute in tenant config
434         final String insertTenantSQL = 
435                 "INSERT INTO tenants (id,name,disabled,created_at) VALUES (?,?,FALSE,now())";
436         PreparedStatement pstmt = null;
437         try {
438                 pstmt = conn.prepareStatement(insertTenantSQL); // create a statement
439                 for(String tId : tenantInfo.keySet()) {
440                         if(existingTenants.contains(tId)) {
441                                 if (logger.isDebugEnabled()) {
442                                         logger.debug("createMissingTenants: tenant exists (skipping): "
443                                                         +tenantInfo.get(tId));
444                                 }
445                                 continue;
446                         }
447                         pstmt.setString(1, tId);                                        // set id param
448                         pstmt.setString(2, tenantInfo.get(tId));        // set name param
449                         if (logger.isDebugEnabled()) {
450                                 logger.debug("createMissingTenants adding entry for tenant: "+tId);
451                         }
452                         pstmt.executeUpdate();
453                 }
454                 pstmt.close();
455         } catch(Exception e) {
456                 throw e;
457         } finally {
458                 if(pstmt!=null)
459                         pstmt.close();
460         }
461     }
462     
463     private static ArrayList<String> findOrCreateDefaultUsers(Connection conn, Hashtable<String, String> tenantInfo) 
464                 throws SQLException, Exception {
465         // Second find or create the users
466         Statement stmt = null;
467         PreparedStatement pstmt = null;
468         ArrayList<String> usersInRepo = new ArrayList<String>();
469         try {
470                 stmt = conn.createStatement();
471                 ResultSet rs = stmt.executeQuery(QUERY_USERS_SQL);
472                 while (rs.next()) {
473                         String uName = rs.getString("username");
474                         usersInRepo.add(uName);
475                 }
476                 rs.close();
477                 pstmt = conn.prepareStatement(INSERT_USER_SQL); // create a statement
478                 for(String tName : tenantInfo.values()) {
479                         String adminAcctName = getDefaultAdminUserID(tName);
480                         if(!usersInRepo.contains(adminAcctName)) {
481                                 String secEncPasswd = SecurityUtils.createPasswordHash(
482                                                 adminAcctName, DEFAULT_ADMIN_PASSWORD);
483                                 pstmt.setString(1, adminAcctName);      // set username param
484                                 pstmt.setString(2, secEncPasswd);       // set passwd param
485                                 if (logger.isDebugEnabled()) {
486                                         logger.debug("createDefaultUsersAndAccounts adding user: "
487                                                         +adminAcctName+" for tenant: "+tName);
488                                 }
489                                 pstmt.executeUpdate();
490                         } else if (logger.isDebugEnabled()) {
491                                 logger.debug("createDefaultUsersAndAccounts: user: "+adminAcctName
492                                                 +" already exists - skipping.");
493                         }
494
495
496                         String readerAcctName =  getDefaultReaderUserID(tName);
497                         if(!usersInRepo.contains(readerAcctName)) {
498                                 String secEncPasswd = SecurityUtils.createPasswordHash(
499                                                 readerAcctName, DEFAULT_READER_PASSWORD);
500                                 pstmt.setString(1, readerAcctName);     // set username param
501                                 pstmt.setString(2, secEncPasswd);       // set passwd param
502                                 if (logger.isDebugEnabled()) {
503                                         logger.debug("createDefaultUsersAndAccounts adding user: "
504                                                         +readerAcctName+" for tenant: "+tName);
505                                 }
506                                 pstmt.executeUpdate();
507                         } else if (logger.isDebugEnabled()) {
508                                 logger.debug("createDefaultUsersAndAccounts: user: "+readerAcctName
509                                                 +" already exists - skipping.");
510                         }
511                 }
512                 pstmt.close();
513         } catch(Exception e) {
514                 throw e;
515         } finally {
516                 if(stmt!=null)
517                         stmt.close();
518                 if(pstmt!=null)
519                         pstmt.close();
520         }
521         return usersInRepo;
522     }
523     
524     private static void findOrCreateDefaultAccounts(Connection conn, Hashtable<String, String> tenantInfo,
525                 ArrayList<String> usersInRepo,
526                 Hashtable<String, String> tenantAdminAcctCSIDs, Hashtable<String, String> tenantReaderAcctCSIDs) 
527                         throws SQLException, Exception {
528         // Third, create the accounts. Assume that if the users were already there,
529         // then the accounts were as well
530         PreparedStatement pstmt = null;
531         try {
532                 pstmt = conn.prepareStatement(INSERT_ACCOUNT_SQL); // create a statement
533                 for(String tId : tenantInfo.keySet()) {
534                         String tName = tenantInfo.get(tId);
535                         String adminCSID = UUID.randomUUID().toString();
536                         tenantAdminAcctCSIDs.put(tId, adminCSID);
537                         String adminAcctName =  getDefaultAdminUserID(tName);
538                         if(!usersInRepo.contains(adminAcctName)) {
539                                 pstmt.setString(1, adminCSID);                  // set csid param
540                                 pstmt.setString(2, adminAcctName);      // set email param (bogus)
541                                 pstmt.setString(3, adminAcctName);      // set userid param
542                                 pstmt.setString(4, "Administrator");// set screen name param
543                                 if (logger.isDebugEnabled()) {
544                                         logger.debug("createDefaultAccounts adding account: "
545                                                         +adminAcctName+" for tenant: "+tName);
546                                 }
547                                 pstmt.executeUpdate();
548                         } else if (logger.isDebugEnabled()) {
549                                 logger.debug("createDefaultAccounts: user: "+adminAcctName
550                                                 +" already exists - skipping account generation.");
551                         }
552
553                         String readerCSID = UUID.randomUUID().toString();       
554                         tenantReaderAcctCSIDs.put(tId, readerCSID);
555                         String readerAcctName =  getDefaultReaderUserID(tName);
556                         if(!usersInRepo.contains(readerAcctName)) {
557                                 pstmt.setString(1, readerCSID);         // set csid param
558                                 pstmt.setString(2, readerAcctName);     // set email param (bogus)
559                                 pstmt.setString(3, readerAcctName);     // set userid param
560                                 pstmt.setString(4, "Reader");           // set screen name param
561                                 if (logger.isDebugEnabled()) {
562                                         logger.debug("createDefaultAccounts adding account: "
563                                                         +readerAcctName+" for tenant: "+tName);
564                                 }
565                                 pstmt.executeUpdate();
566                         } else if (logger.isDebugEnabled()) {
567                                 logger.debug("createDefaultAccounts: user: "+readerAcctName
568                                                 +" already exists - skipping account creation.");
569                         }
570                 }
571                 pstmt.close();
572         } catch(Exception e) {
573                 throw e;
574         } finally {
575                 if(pstmt!=null)
576                         pstmt.close();
577         }
578     }
579     
580     private static boolean findOrCreateTenantManagerUserAndAccount(Connection conn) 
581                         throws SQLException, Exception {
582         // Find or create the special tenant manager account.
583         // Later can make the user name for tenant manager be configurable, settable.
584         Statement stmt = null;
585         PreparedStatement pstmt = null;
586         boolean created = false;
587         try {
588                 boolean foundTMgrUser = false;
589                 stmt = conn.createStatement();
590                 ResultSet rs = stmt.executeQuery(QUERY_TENANT_MGR_USER_SQL);
591                 // Should only find one - only consider it
592                 if(rs.next()) {
593                         String uName = rs.getString("username");
594                         foundTMgrUser = uName.equals(TENANT_MANAGER_USER);
595                 }
596                 rs.close();
597                 if(!foundTMgrUser) {
598                         pstmt = conn.prepareStatement(INSERT_USER_SQL); // create a statement
599                         String secEncPasswd = SecurityUtils.createPasswordHash(
600                                         TENANT_MANAGER_USER, DEFAULT_TENANT_MANAGER_PASSWORD);
601                         pstmt.setString(1, TENANT_MANAGER_USER);        // set username param
602                         pstmt.setString(2, secEncPasswd);       // set passwd param
603                         if (logger.isDebugEnabled()) {
604                                 logger.debug("findOrCreateTenantManagerUserAndAccount adding tenant manager user: "
605                                                 +TENANT_MANAGER_USER);
606                         }
607                         pstmt.executeUpdate();
608                 pstmt.close();
609                 // Now create the account to match
610                         pstmt = conn.prepareStatement(INSERT_ACCOUNT_SQL); // create a statement
611                                 pstmt.setString(1, AuthN.TENANT_MANAGER_ACCT_ID);                // set csid param
612                                 pstmt.setString(2, DEFAULT_TENANT_MANAGER_EMAIL);       // set email param (bogus)
613                                 pstmt.setString(3, TENANT_MANAGER_USER);        // set userid param
614                                 pstmt.setString(4, TENANT_MANAGER_SCREEN_NAME);// set screen name param
615                                 if (logger.isDebugEnabled()) {
616                                         logger.debug("findOrCreateTenantManagerUserAndAccount adding tenant manager account: "
617                                                         +TENANT_MANAGER_USER);
618                                 }
619                                 pstmt.executeUpdate();
620                         pstmt.close();
621                         created = true;
622                 } else if (logger.isDebugEnabled()) {
623                         logger.debug("findOrCreateTenantManagerUserAndAccount: tenant manager: "+TENANT_MANAGER_USER
624                                         +" already exists.");
625                 }
626         } catch(Exception e) {
627                 throw e;
628         } finally {
629                 if(stmt!=null)
630                         stmt.close();
631                 if(pstmt!=null)
632                         pstmt.close();
633         }
634         return created;
635     }
636     
637     private static void bindDefaultAccountsToTenants(Connection conn, DatabaseProductType databaseProductType,
638                 Hashtable<String, String> tenantInfo, ArrayList<String> usersInRepo,
639                 Hashtable<String, String> tenantAdminAcctCSIDs, Hashtable<String, String> tenantReaderAcctCSIDs) 
640                         throws SQLException, Exception {
641         // Fourth, bind accounts to tenants. Assume that if the users were already there,
642         // then the accounts were bound to tenants correctly
643         PreparedStatement pstmt = null;
644         try {
645                 String insertAccountTenantSQL;
646                 if (databaseProductType == DatabaseProductType.MYSQL) {
647                         insertAccountTenantSQL =
648                                         "INSERT INTO accounts_tenants (TENANTS_ACCOUNTS_COMMON_CSID,tenant_id) "
649                                                         + " VALUES(?, ?)";
650                 } else if (databaseProductType == DatabaseProductType.POSTGRESQL) {
651                         insertAccountTenantSQL =
652                                         "INSERT INTO accounts_tenants (HJID, TENANTS_ACCOUNTS_COMMON_CSID,tenant_id) "
653                                                         + " VALUES(nextval('hibernate_sequence'), ?, ?)";
654                 } else {
655                         throw new Exception("Unrecognized database system.");
656                 }
657                 pstmt = conn.prepareStatement(insertAccountTenantSQL); // create a statement
658                 for(String tId : tenantInfo.keySet()) {
659                         String tName = tenantInfo.get(tId);
660                         if(!usersInRepo.contains(getDefaultAdminUserID(tName))) {
661                                 String adminAcct = tenantAdminAcctCSIDs.get(tId);
662                                 pstmt.setString(1, adminAcct);          // set acct CSID param
663                                 pstmt.setString(2, tId);                        // set tenant_id param
664                                 if (logger.isDebugEnabled()) {
665                                         logger.debug("createDefaultAccounts binding account id: "
666                                                         +adminAcct+" to tenant id: "+tId);
667                                 }
668                                 pstmt.executeUpdate();
669                         }
670                         if(!usersInRepo.contains(getDefaultReaderUserID(tName))) {
671                                 String readerAcct = tenantReaderAcctCSIDs.get(tId);
672                                 pstmt.setString(1, readerAcct);         // set acct CSID param
673                                 pstmt.setString(2, tId);                        // set tenant_id param
674                                 if (logger.isDebugEnabled()) {
675                                         logger.debug("createDefaultAccounts binding account id: "
676                                                         +readerAcct+" to tenant id: "+tId);
677                                 }
678                                 pstmt.executeUpdate();
679                         }
680                 }
681                 pstmt.close();
682         } catch(Exception e) {
683                 throw e;
684         } finally {
685                 if(pstmt!=null)
686                         pstmt.close();
687         }
688     }
689     
690     
691     private static String findOrCreateDefaultRoles(Connection conn, Hashtable<String, String> tenantInfo,
692                 Hashtable<String, String> tenantAdminRoleCSIDs, Hashtable<String, String> tenantReaderRoleCSIDs) 
693                         throws SQLException, Exception {
694         // Fifth, fetch and save the default roles
695                 String springAdminRoleCSID = null;
696         Statement stmt = null;
697         PreparedStatement pstmt = null;
698         try {
699                 final String querySpringRole = 
700                                 "SELECT csid from roles WHERE rolename='"+SPRING_ADMIN_ROLE+"'";
701                 stmt = conn.createStatement();
702                 ResultSet rs = stmt.executeQuery(querySpringRole);
703                 if(rs.next()) {
704                         springAdminRoleCSID = rs.getString(1);
705                         if (logger.isDebugEnabled()) {
706                                 logger.debug("createDefaultAccounts found Spring Admin role: "
707                                                 +springAdminRoleCSID);
708                         }
709                 } else {
710                         final String insertSpringAdminRoleSQL =
711                                         "INSERT INTO roles (csid, rolename, displayName, rolegroup, created_at, tenant_id) "
712                                                         + "VALUES ('-1', 'ROLE_SPRING_ADMIN', 'SPRING_ADMIN', 'Spring Security Administrator', now(), '0')";
713                         stmt.executeUpdate(insertSpringAdminRoleSQL);
714                         springAdminRoleCSID = "-1";
715                         if (logger.isDebugEnabled()) {
716                                 logger.debug("createDefaultAccounts CREATED Spring Admin role: "
717                                                 +springAdminRoleCSID);
718                         }
719                 }
720                 rs.close();
721                 final String getRoleCSIDSql =
722                                 "SELECT csid from roles WHERE tenant_id=? and rolename=?";
723                 pstmt = conn.prepareStatement(getRoleCSIDSql); // create a statement
724                 rs = null;
725                 for(String tId : tenantInfo.keySet()) {
726                         pstmt.setString(1, tId);                                                // set tenant_id param
727                         pstmt.setString(2, getDefaultAdminRole(tId));   // set rolename param
728                         rs = pstmt.executeQuery();
729                         // extract data from the ResultSet
730                         if(!rs.next()) {
731                                 throw new RuntimeException("Cannot find role: "+getDefaultAdminRole(tId)
732                                                 +" for tenant id: "+tId+" in roles!");
733                         }
734                         String tenantAdminRoleCSID = rs.getString(1);
735                         if (logger.isDebugEnabled()) {
736                                 logger.debug("createDefaultAccounts found role: "
737                                                 +getDefaultAdminRole(tId)+"("+tenantAdminRoleCSID
738                                                 +") for tenant id: "+tId);
739                         }
740                         tenantAdminRoleCSIDs.put(tId, tenantAdminRoleCSID);
741                         pstmt.setString(1, tId);                                                // set tenant_id param
742                         pstmt.setString(2, getDefaultReaderRole(tId));  // set rolename param
743                         rs.close();
744                         rs = pstmt.executeQuery();
745                         // extract data from the ResultSet
746                         if(!rs.next()) {
747                                 throw new RuntimeException("Cannot find role: "+getDefaultReaderRole(tId)
748                                                 +" for tenant id: "+tId+" in roles!");
749                         }
750                         String tenantReaderRoleCSID = rs.getString(1);
751                         if (logger.isDebugEnabled()) {
752                                 logger.debug("createDefaultAccounts found role: "
753                                                 +getDefaultReaderRole(tId)+"("+tenantReaderRoleCSID
754                                                 +") for tenant id: "+tId);
755                         }
756                         tenantReaderRoleCSIDs.put(tId, tenantReaderRoleCSID);
757                         rs.close();
758                 }
759                 pstmt.close();
760         } catch(Exception e) {
761                 throw e;
762         } finally {
763                 if(stmt!=null)
764                         stmt.close();
765                 if(pstmt!=null)
766                         pstmt.close();
767         }
768         return springAdminRoleCSID;
769     }
770
771     private static String findTenantManagerRole(Connection conn ) 
772                         throws SQLException, RuntimeException, Exception {
773                 String tenantMgrRoleCSID = null;
774         PreparedStatement pstmt = null;
775         try {
776                 String rolename = getQualifiedRoleName(ALL_TENANTS_MANAGER_TENANT_ID, 
777                                                                                                 ROLE_ALL_TENANTS_MANAGER);              
778                 pstmt = conn.prepareStatement(GET_TENANT_MGR_ROLE_SQL); // create a statement
779                 ResultSet rs = null;
780                 pstmt.setString(1, rolename);   // set rolename param
781                 rs = pstmt.executeQuery();
782                 if(rs.next()) {
783                         tenantMgrRoleCSID = rs.getString(1);
784                         if (logger.isDebugEnabled()) {
785                                 logger.debug("findTenantManagerRole found Tenant Mgr role: "
786                                                 +tenantMgrRoleCSID);
787                         }
788                 }
789                 rs.close();
790         } catch(Exception e) {
791                 throw e;
792         } finally {
793                 if(pstmt!=null)
794                         pstmt.close();
795         }
796         if(tenantMgrRoleCSID==null)
797                 throw new RuntimeException("findTenantManagerRole: Cound not find tenant Manager Role!");
798         return tenantMgrRoleCSID;
799     }
800
801     private static void bindAccountsToRoles(Connection conn,  DatabaseProductType databaseProductType,
802                 Hashtable<String, String> tenantInfo, ArrayList<String> usersInRepo,
803                 String springAdminRoleCSID,
804                 Hashtable<String, String> tenantAdminRoleCSIDs, Hashtable<String, String> tenantReaderRoleCSIDs,
805                 Hashtable<String, String> tenantAdminAcctCSIDs, Hashtable<String, String> tenantReaderAcctCSIDs) 
806                         throws SQLException, Exception {
807         // Sixth, bind the accounts to roles. If the users already existed,
808         // we'll assume they were set up correctly.
809         PreparedStatement pstmt = null;
810         try {
811                 String insertAccountRoleSQL;
812                 if (databaseProductType == DatabaseProductType.MYSQL) {
813                         insertAccountRoleSQL = INSERT_ACCOUNT_ROLE_SQL_MYSQL;
814                 } else if (databaseProductType == DatabaseProductType.POSTGRESQL) {
815                         insertAccountRoleSQL = INSERT_ACCOUNT_ROLE_SQL_POSTGRES;
816                 } else {
817                         throw new Exception("Unrecognized database system.");
818                 }
819                 if (logger.isDebugEnabled()) {
820                         logger.debug("createDefaultAccounts binding accounts to roles with SQL:\n"
821                                         +insertAccountRoleSQL);
822                 }
823                 pstmt = conn.prepareStatement(insertAccountRoleSQL); // create a statement
824                 for(String tId : tenantInfo.keySet()) {
825                         String adminUserId =  getDefaultAdminUserID(tenantInfo.get(tId));
826                         if(!usersInRepo.contains(adminUserId)) {
827                                 String adminAcct = tenantAdminAcctCSIDs.get(tId);
828                                 String adminRoleId = tenantAdminRoleCSIDs.get(tId);
829                                 pstmt.setString(1, adminAcct);          // set acct CSID param
830                                 pstmt.setString(2, adminUserId);        // set user_id param
831                                 pstmt.setString(3, adminRoleId);        // set role_id param
832                                 pstmt.setString(4, getDefaultAdminRole(tId));   // set rolename param
833                                 if (logger.isDebugEnabled()) {
834                                         logger.debug("createDefaultAccounts binding account: "
835                                                         +adminUserId+" to Admin role("+adminRoleId
836                                                         +") for tenant id: "+tId);
837                                 }
838                                 pstmt.executeUpdate();
839                                 // Now add the Spring Admin Role to the admin accounts
840                                 pstmt.setString(3, springAdminRoleCSID);        // set role_id param
841                                 pstmt.setString(4, SPRING_ADMIN_ROLE);          // set rolename param
842                                 if (logger.isDebugEnabled()) {
843                                         logger.debug("createDefaultAccounts binding account: "
844                                                         +adminUserId+" to Spring Admin role: "+springAdminRoleCSID);
845                                 }
846                                 pstmt.executeUpdate();
847                         }
848                         String readerUserId = getDefaultReaderUserID(tenantInfo.get(tId));
849                         if(!usersInRepo.contains(readerUserId)) {
850                                 String readerAcct = tenantReaderAcctCSIDs.get(tId);
851                                 String readerRoleId = tenantReaderRoleCSIDs.get(tId);
852                                 pstmt.setString(1, readerAcct);         // set acct CSID param
853                                 pstmt.setString(2, readerUserId);       // set user_id param
854                                 pstmt.setString(3, readerRoleId);       // set role_id param
855                                 pstmt.setString(4, getDefaultReaderRole(tId));  // set rolename param
856                                 if (logger.isDebugEnabled()) {
857                                         logger.debug("createDefaultAccounts binding account: "
858                                                         +readerUserId+" to Reader role("+readerRoleId
859                                                         +") for tenant id: "+tId);
860                                 }
861                                 pstmt.executeUpdate();
862                         }
863                 }
864                 pstmt.close();
865         } catch(Exception e) {
866                 throw e;
867         } finally {
868                 if(pstmt!=null)
869                         pstmt.close();
870         }
871     }
872     
873     private static void bindTenantManagerAccountRole(Connection conn,  DatabaseProductType databaseProductType,
874                 String tenantManagerUserID, String tenantManagerAccountID, String tenantManagerRoleID, String tenantManagerRoleName ) 
875                         throws SQLException, Exception {
876         PreparedStatement pstmt = null;
877         try {
878                 String insertAccountRoleSQL;
879                 if (databaseProductType == DatabaseProductType.MYSQL) {
880                         insertAccountRoleSQL = INSERT_ACCOUNT_ROLE_SQL_MYSQL;
881                 } else if (databaseProductType == DatabaseProductType.POSTGRESQL) {
882                         insertAccountRoleSQL = INSERT_ACCOUNT_ROLE_SQL_POSTGRES;
883                 } else {
884                         throw new Exception("Unrecognized database system.");
885                 }
886                 if (logger.isDebugEnabled()) {
887                         logger.debug("bindTenantManagerAccountRole binding account to role with SQL:\n"
888                                         +insertAccountRoleSQL);
889                 }
890                 pstmt = conn.prepareStatement(insertAccountRoleSQL); // create a statement
891                 pstmt.setString(1, tenantManagerAccountID);             // set acct CSID param
892                 pstmt.setString(2, tenantManagerUserID);        // set user_id param
893                 pstmt.setString(3, tenantManagerRoleID);        // set role_id param
894                 pstmt.setString(4, tenantManagerRoleName);      // set rolename param
895                 if (logger.isDebugEnabled()) {
896                         logger.debug("bindTenantManagerAccountRole binding user: "
897                                         +tenantManagerUserID+" to Admin role("+tenantManagerRoleName+")");
898                 }
899                 pstmt.executeUpdate();
900                 /* At this point, tenant manager should not need the Spring Admin Role
901                 pstmt.setString(3, springAdminRoleCSID);        // set role_id param
902                 pstmt.setString(4, SPRING_ADMIN_ROLE);          // set rolename param
903                 if (logger.isDebugEnabled()) {
904                         logger.debug("createDefaultAccounts binding account: "
905                                         +adminUserId+" to Spring Admin role: "+springAdminRoleCSID);
906                 }
907                 pstmt.executeUpdate();
908                 */
909                 pstmt.close();
910         } catch(Exception e) {
911                 throw e;
912         } finally {
913                 if(pstmt!=null)
914                         pstmt.close();
915         }
916     }
917     
918     public static void createDefaultAccounts(
919                 TenantBindingConfigReaderImpl tenantBindingConfigReader,
920                 DatabaseProductType databaseProductType,
921                 String cspaceDatabaseName) throws Exception {
922
923         logger.debug("ServiceMain.createDefaultAccounts starting...");
924         
925         Hashtable<String, String> tenantInfo = getTenantNamesFromConfig(tenantBindingConfigReader);
926         Connection conn = null;
927         // TODO - need to put in tests for existence first.
928         // We could just look for the accounts per tenant up front, and assume that
929         // the rest is there if the accounts are.
930         // Could add a sql script to remove these if need be - Spring only does roles, 
931         // and we're not touching that, so we could safely toss the 
932         // accounts, users, account-tenants, account-roles, and start over.
933         try {
934                 conn = getConnection(cspaceDatabaseName);
935                 ArrayList<String> existingTenants = compileExistingTenants(conn, tenantInfo);
936                 
937                 // Note that this only creates tenants not marked as "createDisabled"
938                 createMissingTenants(conn, tenantInfo, existingTenants);
939                 
940                 ArrayList<String> usersInRepo = findOrCreateDefaultUsers(conn, tenantInfo);
941                 
942                 Hashtable<String, String> tenantAdminAcctCSIDs = new Hashtable<String, String>();
943                 Hashtable<String, String> tenantReaderAcctCSIDs = new Hashtable<String, String>();
944                 findOrCreateDefaultAccounts(conn, tenantInfo, usersInRepo,
945                                 tenantAdminAcctCSIDs, tenantReaderAcctCSIDs);
946
947                 bindDefaultAccountsToTenants(conn, databaseProductType, tenantInfo, usersInRepo,
948                                 tenantAdminAcctCSIDs, tenantReaderAcctCSIDs);
949                 
950                 Hashtable<String, String> tenantAdminRoleCSIDs = new Hashtable<String, String>();
951                 Hashtable<String, String> tenantReaderRoleCSIDs = new Hashtable<String, String>();
952                 String springAdminRoleCSID = findOrCreateDefaultRoles(conn, tenantInfo,
953                                 tenantAdminRoleCSIDs, tenantReaderRoleCSIDs);
954                 
955                 bindAccountsToRoles(conn,  databaseProductType,
956                                 tenantInfo, usersInRepo, springAdminRoleCSID,
957                                 tenantAdminRoleCSIDs, tenantReaderRoleCSIDs,
958                                 tenantAdminAcctCSIDs, tenantReaderAcctCSIDs);
959                 
960                 boolean createdTenantMgrAccount = findOrCreateTenantManagerUserAndAccount(conn);
961                 if(createdTenantMgrAccount) {
962                         // If we created the account, we need to create the bindings. Otherwise, assume they
963                         // are all set (from previous initialization).
964                         String tenantManagerRoleCSID = findTenantManagerRole(conn);
965                         bindTenantManagerAccountRole(conn, databaseProductType, 
966                                         TENANT_MANAGER_USER, AuthN.TENANT_MANAGER_ACCT_ID, 
967                                         tenantManagerRoleCSID, ROLE_ALL_TENANTS_MANAGER);
968                 }
969         } catch (Exception e) {
970                         logger.debug("Exception in createDefaultAccounts: " + e.getLocalizedMessage());
971                 throw e;
972                 } finally {
973                         try {
974                                 if (conn != null)
975                                         conn.close();
976                         } catch (SQLException sqle) {
977                                 if (logger.isDebugEnabled()) {
978                                         logger.debug("SQL Exception closing statement/connection: " + sqle.getLocalizedMessage());
979                                 }
980                         }
981                 }       
982     }
983     
984     private static String getDefaultAdminRole(String tenantId) {
985         return ROLE_PREFIX+tenantId+TENANT_ADMIN_ROLE_SUFFIX;
986     }
987     
988     private static String getDefaultReaderRole(String tenantId) {
989         return ROLE_PREFIX+tenantId+TENANT_READER_ROLE_SUFFIX;
990     }
991     
992     private static String getDefaultAdminUserID(String tenantName) {
993         return TENANT_ADMIN_ACCT_PREFIX+tenantName;
994     }
995     
996     private static String getDefaultReaderUserID(String tenantName) {
997         return TENANT_READER_ACCT_PREFIX+tenantName;
998     }
999     
1000         static public PermissionAction createPermissionAction(Permission perm,
1001                         ActionType actionType) {
1002         PermissionAction pa = new PermissionAction();
1003
1004             CSpaceAction action = URIResourceImpl.getAction(actionType);
1005             URIResourceImpl uriRes = new URIResourceImpl(perm.getTenantId(),
1006                     perm.getResourceName(), action);
1007             pa.setName(actionType);
1008             pa.setObjectIdentity(uriRes.getHashedId().toString());
1009             pa.setObjectIdentityResource(uriRes.getId());
1010             
1011             return pa;
1012         }
1013
1014         static public PermissionAction update(Permission perm, PermissionAction permAction) {
1015         PermissionAction pa = new PermissionAction();
1016
1017             CSpaceAction action = URIResourceImpl.getAction(permAction.getName());
1018             URIResourceImpl uriRes = new URIResourceImpl(perm.getTenantId(),
1019                     perm.getResourceName(), action);
1020             pa.setObjectIdentity(uriRes.getHashedId().toString());
1021             pa.setObjectIdentityResource(uriRes.getId());
1022             
1023             return pa;
1024         }
1025         
1026         private static TransitionDefList getTransitionDefList(TenantBindingType tenantBinding, ServiceBindingType serviceBinding) {
1027                 TransitionDefList result = null;
1028                 try {
1029                         String serviceObjectName = serviceBinding.getObject().getName();
1030                 DocumentHandler docHandler = ServiceConfigUtils.createDocumentHandlerInstance(
1031                                 tenantBinding, serviceBinding);
1032                 Lifecycle lifecycle = docHandler.getLifecycle(serviceObjectName);
1033                 if (lifecycle != null) {
1034                         result = lifecycle.getTransitionDefList();
1035                 }
1036                 } catch (Exception e) {
1037                         // Ignore this exception and return an empty non-null TransitionDefList
1038                 }
1039                 
1040                 if (result == null) {
1041                         if (serviceBinding.getType().equalsIgnoreCase(ServiceBindingUtils.SERVICE_TYPE_SECURITY) == false) {
1042                                 logger.warn("Could not retrieve a lifecycle transition definition list from: "
1043                                                 + serviceBinding.getName()
1044                                                 + " with tenant ID = "
1045                                                 + tenantBinding.getId());
1046                         }
1047                         // return an empty list                 
1048                         result = new TransitionDefList();
1049                 } else {
1050                         logger.debug("Successfully retrieved a lifecycle transition definition list from: "
1051                                         + serviceBinding.getName()
1052                                         + " with tenant ID = "
1053                                         + tenantBinding.getId());
1054                 }
1055                 
1056                 return result;
1057         }
1058         
1059     public static void createDefaultWorkflowPermissions(TenantBindingConfigReaderImpl tenantBindingConfigReader) throws Exception //FIXME: REM - 4/11/2012 - Rename to createWorkflowPermissions
1060     {
1061         AuthZ.get().login(); //login to Spring Security manager
1062         
1063         EntityManagerFactory emf = JpaStorageUtils.getEntityManagerFactory(JpaStorageUtils.CS_PERSISTENCE_UNIT);
1064         EntityManager em = null;
1065
1066         try {
1067             em = emf.createEntityManager();
1068
1069                 Hashtable<String, TenantBindingType> tenantBindings =
1070                         tenantBindingConfigReader.getTenantBindings();
1071                 for (String tenantId : tenantBindings.keySet()) {
1072                         TenantBindingType tenantBinding = tenantBindings.get(tenantId);
1073                         Role adminRole = AuthorizationCommon.getRole(em, tenantBinding.getId(), ROLE_TENANT_ADMINISTRATOR);
1074                         Role readonlyRole = AuthorizationCommon.getRole(em, tenantBinding.getId(), ROLE_TENANT_READER);
1075                         for (ServiceBindingType serviceBinding : tenantBinding.getServiceBindings()) {
1076                                 String prop = ServiceBindingUtils.getPropertyValue(serviceBinding, REFRESH_AUTZ_PROP);
1077                                 if (prop == null ? true : Boolean.parseBoolean(prop)) {
1078                                                 try {
1079                                                 em.getTransaction().begin();
1080                                                 TransitionDefList transitionDefList = getTransitionDefList(tenantBinding, serviceBinding);
1081                                                 for (TransitionDef transitionDef : transitionDefList.getTransitionDef()) {
1082                                                         //
1083                                                         // Create the permission for the admin role
1084                                                         Permission adminPerm = createWorkflowPermission(tenantBinding, serviceBinding, transitionDef, ACTIONGROUP_CRUDL);
1085                                                         persist(em, adminPerm, adminRole, true);
1086                                                         //
1087                                                         // Create the permission for the read-only role
1088                                                         Permission readonlyPerm = createWorkflowPermission(tenantBinding, serviceBinding, transitionDef, ACTIONGROUP_RL);
1089                                                         
1090                                                         Profiler profiler = new Profiler(AuthorizationCommon.class, 1);
1091                                                         profiler.start("createDefaultPermissions started:" + readonlyPerm.getCsid());
1092                                                         persist(em, readonlyPerm, readonlyRole, true); // Persist/store the permission and permrole records and related Spring Security info
1093                                                         profiler.stop();
1094                                                         logger.debug("Finished full perm generation for "
1095                                                                         + ":" + tenantBinding.getId()
1096                                                                         + ":" + serviceBinding.getName()
1097                                                                         + ":" + transitionDef.getName()
1098                                                                         + ":" + ACTIONGROUP_RL
1099                                                                         + ":" + profiler.getCumulativeTime());                                          
1100                                                 }
1101                                                 em.getTransaction().commit();
1102                                         } catch (IllegalStateException e) {
1103                                                 logger.debug(e.getLocalizedMessage(), e); //We end up here if there is no document handler for the service -this is ok for some of the services.
1104                                         }
1105                                 } else {
1106                                         logger.warn("AuthZ refresh service binding property is set to FALSE so default permissions will NOT be refreshed for: "
1107                                                         + serviceBinding.getName());
1108                                 }
1109                         }
1110                 }
1111             em.close();
1112         } catch (Exception e) {
1113             if (em != null && em.getTransaction().isActive()) {
1114                 em.getTransaction().rollback();
1115             }
1116             if (logger.isDebugEnabled()) {
1117                 logger.debug("Caught exception and rolling back permission creation: ", e);
1118             }
1119             throw e;
1120         } finally {
1121             if (em != null) {
1122                 JpaStorageUtils.releaseEntityManagerFactory(emf);
1123             }
1124         }
1125     }
1126     
1127     private static PermissionRoleRel findPermRoleRel(EntityManager em, String permissionId, String RoleId) {
1128         PermissionRoleRel result = null;
1129         
1130         try {
1131                 String whereClause = "where permissionId = :id and roleId = :roleId";
1132                 HashMap<String, Object> params = new HashMap<String, Object>();
1133                 params.put("id", permissionId);
1134                 params.put("roleId", RoleId);        
1135         
1136                 result = (PermissionRoleRel) JpaStorageUtils.getEntity(em,
1137                                 PermissionRoleRel.class.getCanonicalName(), whereClause, params);
1138         } catch (Exception e) {
1139                 //Do nothing. Will return null;
1140         }
1141                 
1142         return result;
1143     }
1144     
1145     /*
1146      * Persists the Permission, PermissionRoleRel, and Spring Security table entries all in one transaction
1147      */
1148     private static void persist(EntityManager em, Permission permission, Role role, boolean enforceTenancy) throws Exception {
1149                 AuthorizationStore authzStore = new AuthorizationStore();
1150                 // First persist the Permission record
1151                 authzStore.store(em, permission);
1152                 
1153                 // If the PermRoleRel doesn't already exists then relate the permission and the role in a new PermissionRole (the service payload)
1154                 // Create a PermissionRoleRel (the database relation table for the permission and role)
1155                 PermissionRoleRel permRoleRel = findPermRoleRel(em, permission.getCsid(), role.getCsid());
1156                 if (permRoleRel == null) {
1157                         PermissionRole permRole = createPermissionRole(em, permission, role, enforceTenancy);
1158                 List<PermissionRoleRel> permRoleRels = new ArrayList<PermissionRoleRel>();
1159                 PermissionRoleUtil.buildPermissionRoleRel(em, permRole, SubjectType.ROLE, permRoleRels, false /*not for delete*/);
1160                 for (PermissionRoleRel prr : permRoleRels) {
1161                     authzStore.store(em, prr);
1162                 }
1163                         Profiler profiler = new Profiler(AuthorizationCommon.class, 2);
1164                         profiler.start();
1165                         // Add a corresponding entry in the Spring Security Tables
1166                         addPermissionsForUri(permission, permRole);
1167                         profiler.stop();
1168                         logger.debug("Finished full perm generation for "
1169                                         + ":" + permission.getTenantId()
1170                                         + ":" + permission.getResourceName()
1171                                         + ":" + ACTIONGROUP_RL
1172                                         + ":" + profiler.getCumulativeTime());
1173                 }
1174         
1175     }
1176
1177 }