Coverage Report - org.kuali.rice.kim.service.impl.RoleManagementServiceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
RoleManagementServiceImpl
0%
0/403
0%
0/148
2.25
 
 1  
 /*
 2  
  * Copyright 2007-2008 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.kuali.rice.kim.service.impl;
 17  
 
 18  
 import org.apache.commons.lang.exception.ExceptionUtils;
 19  
 import org.apache.log4j.Logger;
 20  
 import org.kuali.rice.core.util.AttributeSet;
 21  
 import org.kuali.rice.core.util.MaxAgeSoftReference;
 22  
 import org.kuali.rice.core.util.MaxSizeMap;
 23  
 import org.kuali.rice.kim.api.entity.principal.Principal;
 24  
 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
 25  
 import org.kuali.rice.kim.api.type.KimType;
 26  
 import org.kuali.rice.kim.api.type.KimTypeInfoService;
 27  
 import org.kuali.rice.kim.bo.Role;
 28  
 
 29  
 import org.kuali.rice.kim.bo.role.dto.DelegateMemberCompleteInfo;
 30  
 import org.kuali.rice.kim.bo.role.dto.DelegateTypeInfo;
 31  
 import org.kuali.rice.kim.bo.role.dto.KimRoleInfo;
 32  
 import org.kuali.rice.kim.bo.role.dto.RoleMemberCompleteInfo;
 33  
 import org.kuali.rice.kim.bo.role.dto.RoleMembershipInfo;
 34  
 import org.kuali.rice.kim.bo.role.dto.RoleResponsibilityActionInfo;
 35  
 import org.kuali.rice.kim.bo.role.dto.RoleResponsibilityInfo;
 36  
 import org.kuali.rice.kim.framework.type.KimRoleTypeService;
 37  
 import org.kuali.rice.kim.service.KIMServiceLocatorInternal;
 38  
 import org.kuali.rice.kim.service.RoleManagementService;
 39  
 import org.kuali.rice.kim.service.RoleService;
 40  
 import org.kuali.rice.kim.service.RoleUpdateService;
 41  
 import org.kuali.rice.kim.service.support.KimTypeService;
 42  
 import org.springframework.beans.factory.InitializingBean;
 43  
 
 44  
 import javax.jws.WebParam;
 45  
 import java.sql.Date;
 46  
 import java.util.ArrayList;
 47  
 import java.util.Collection;
 48  
 import java.util.Collections;
 49  
 import java.util.HashMap;
 50  
 import java.util.HashSet;
 51  
 import java.util.Iterator;
 52  
 import java.util.List;
 53  
 import java.util.Map;
 54  
 import java.util.Set;
 55  
 
 56  
 /**
 57  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 58  
  */
 59  0
 public class RoleManagementServiceImpl implements RoleManagementService, InitializingBean {
 60  0
         private static final Logger LOG = Logger.getLogger( RoleManagementServiceImpl.class );
 61  
         
 62  
         private RoleService roleService;
 63  
         private KimTypeInfoService typeInfoService;
 64  
         private RoleUpdateService roleUpdateService;
 65  
         
 66  
         // Max age defined in seconds
 67  0
         protected int roleCacheMaxSize = 200;
 68  0
         protected int roleCacheMaxAgeSeconds = 30;
 69  
         
 70  
         protected Map<String,MaxAgeSoftReference<KimRoleInfo>> roleByIdCache;
 71  
         protected Map<String,MaxAgeSoftReference<KimRoleInfo>> roleByNameCache;
 72  
         protected Map<String,MaxAgeSoftReference<List<RoleMembershipInfo>>> roleMembersWithDelegationCache;
 73  
         protected Map<String,MaxAgeSoftReference<List<AttributeSet>>> roleQualifiersForPrincipalCache;
 74  
         protected Map<String,MaxAgeSoftReference<Boolean>> principalHasRoleCache;
 75  
         protected Map<String,MaxAgeSoftReference<Collection<String>>> memberPrincipalIdsCache;
 76  
         
 77  
         protected Map<String, Boolean> shouldCacheRoleCache;
 78  
         
 79  
         public void afterPropertiesSet() throws Exception {
 80  0
                 roleByIdCache = Collections.synchronizedMap( new MaxSizeMap<String,MaxAgeSoftReference<KimRoleInfo>>( roleCacheMaxSize ) );
 81  0
                 roleByNameCache = Collections.synchronizedMap( new MaxSizeMap<String,MaxAgeSoftReference<KimRoleInfo>>( roleCacheMaxSize ) );
 82  0
                 roleMembersWithDelegationCache = Collections.synchronizedMap( new MaxSizeMap<String,MaxAgeSoftReference<List<RoleMembershipInfo>>>( roleCacheMaxSize ) );
 83  0
                 roleQualifiersForPrincipalCache = Collections.synchronizedMap( new MaxSizeMap<String,MaxAgeSoftReference<List<AttributeSet>>>( roleCacheMaxSize ) );
 84  0
                 principalHasRoleCache = Collections.synchronizedMap( new MaxSizeMap<String,MaxAgeSoftReference<Boolean>>( roleCacheMaxSize ) );
 85  0
                 memberPrincipalIdsCache = Collections.synchronizedMap( new MaxSizeMap<String,MaxAgeSoftReference<Collection<String>>>( roleCacheMaxSize ) );
 86  0
                 shouldCacheRoleCache = Collections.synchronizedMap(new HashMap<String, Boolean>());
 87  0
         }
 88  
         
 89  
         public void flushRoleCaches() {
 90  0
                 flushInternalRoleCache();
 91  0
                 flushInternalRoleMemberCache();
 92  0
                 flushInternalDelegationCache();
 93  0
                 flushInternalDelegationMemberCache();
 94  0
                 roleByIdCache.clear();
 95  0
                 roleByNameCache.clear();
 96  0
                 roleMembersWithDelegationCache.clear();
 97  0
                 roleQualifiersForPrincipalCache.clear();
 98  0
                 principalHasRoleCache.clear();
 99  0
                 memberPrincipalIdsCache.clear();
 100  0
                 shouldCacheRoleCache.clear();
 101  0
         }
 102  
         
 103  
         public void flushRoleMemberCaches() {
 104  0
                 flushInternalRoleMemberCache();
 105  0
                 roleMembersWithDelegationCache.clear();
 106  0
                 memberPrincipalIdsCache.clear();
 107  0
         }
 108  
         
 109  
         public void flushDelegationCaches() {
 110  0
                 flushInternalDelegationCache();
 111  0
                 flushInternalDelegationMemberCache();
 112  0
                 roleMembersWithDelegationCache.clear();
 113  0
         }
 114  
         
 115  
         public void flushDelegationMemberCaches() {
 116  0
                 flushInternalDelegationMemberCache();
 117  0
                 roleMembersWithDelegationCache.clear();
 118  0
         }
 119  
         
 120  
         // Caching helper methods
 121  
 
 122  
         protected KimRoleInfo getRoleByIdCache( String roleId ) {
 123  0
                 MaxAgeSoftReference<KimRoleInfo> roleRef = roleByIdCache.get( roleId );
 124  0
                 if ( roleRef != null ) {
 125  0
                         return roleRef.get();
 126  
                 }
 127  0
                 return null;
 128  
         }
 129  
 
 130  
         protected KimRoleInfo getRoleByNameCache( String key ) {
 131  0
                 MaxAgeSoftReference<KimRoleInfo> roleRef = roleByNameCache.get( key );
 132  0
                 if ( roleRef != null ) {
 133  0
                         return roleRef.get();
 134  
                 }
 135  0
                 return null;
 136  
         }
 137  
         
 138  
         protected List<RoleMembershipInfo> getRoleMembersWithDelegationCache( String key ) {
 139  0
                 MaxAgeSoftReference<List<RoleMembershipInfo>> roleMembersRef = roleMembersWithDelegationCache.get( key );
 140  0
                 if ( roleMembersRef != null ) {
 141  0
                         return roleMembersRef.get();
 142  
                 }
 143  0
                 return null;
 144  
         }
 145  
         
 146  
         protected List<AttributeSet> getRoleQualifiersForPrincipalCache( String key ) {
 147  0
                 MaxAgeSoftReference<List<AttributeSet>> qualifiersRef = roleQualifiersForPrincipalCache.get( key );
 148  0
                 if ( qualifiersRef != null ) {
 149  0
                         return qualifiersRef.get();
 150  
                 }
 151  0
                 return null;
 152  
         }
 153  
         
 154  
         protected Boolean getPrincipalHasRoleCacheCache( String key ) {
 155  0
                 MaxAgeSoftReference<Boolean> hasRoleRef = principalHasRoleCache.get( key );
 156  0
                 if ( hasRoleRef != null ) {
 157  0
                         return hasRoleRef.get();
 158  
                 }
 159  0
                 return null;
 160  
         }
 161  
         
 162  
         protected void addRoleToCaches( KimRoleInfo role ) {
 163  0
                 if ( role != null ) {
 164  0
                         roleByNameCache.put( role.getNamespaceCode() + "-" + role.getRoleName(), new MaxAgeSoftReference<KimRoleInfo>( roleCacheMaxAgeSeconds, role ) );
 165  0
                         roleByIdCache.put( role.getRoleId(), new MaxAgeSoftReference<KimRoleInfo>( roleCacheMaxAgeSeconds, role ) );
 166  
                 }
 167  0
         }
 168  
 
 169  
         protected void addRoleMembersWithDelegationToCache( String key, List<RoleMembershipInfo> members ) {
 170  0
                 if ( members != null ) {
 171  0
                         roleMembersWithDelegationCache.put( key, new MaxAgeSoftReference<List<RoleMembershipInfo>>( roleCacheMaxAgeSeconds, members ) );
 172  
                 }
 173  0
         }
 174  
 
 175  
         protected void addRoleQualifiersForPrincipalToCache( String key, List<AttributeSet> qualifiers ) {
 176  0
                 if ( qualifiers != null ) {
 177  0
                         roleQualifiersForPrincipalCache.put( key, new MaxAgeSoftReference<List<AttributeSet>>( roleCacheMaxAgeSeconds, qualifiers ) );
 178  
                 }
 179  0
         }
 180  
         
 181  
         protected void addPrincipalHasRoleToCache( String key, boolean hasRole ) {
 182  0
                 principalHasRoleCache.put( key, new MaxAgeSoftReference<Boolean>( roleCacheMaxAgeSeconds, hasRole ) );
 183  0
         }
 184  
                 
 185  
         // Cached methods
 186  
 
 187  
         protected Collection<String> getRoleMemberPrincipalIdsCache(String key) {
 188  0
                 MaxAgeSoftReference<Collection<String>> memberPrincipalIdsRef = memberPrincipalIdsCache.get(key);
 189  0
                 if ( memberPrincipalIdsRef != null ) {
 190  0
                         return memberPrincipalIdsRef.get();
 191  
                 }
 192  0
                 return null;
 193  
         }
 194  
         
 195  
         protected void addRoleMemberPrincipalIdsToCache(String key, Collection<String> principalIds) {
 196  0
                 memberPrincipalIdsCache.put(key, new MaxAgeSoftReference<Collection<String>>(roleCacheMaxAgeSeconds, principalIds ));
 197  0
         }
 198  
         
 199  
         /**
 200  
          * @see org.kuali.rice.kim.service.RoleService#getRoleMemberPrincipalIds(java.lang.String, java.lang.String, org.kuali.rice.core.util.AttributeSet)
 201  
          */
 202  
         public Collection<String> getRoleMemberPrincipalIds(String namespaceCode, String roleName, AttributeSet qualification) {
 203  0
                 StringBuffer cacheKey = new StringBuffer();
 204  0
                 cacheKey.append( namespaceCode ).append( '/' ).append( roleName );
 205  0
                 addAttributesToKey(cacheKey, qualification);
 206  0
                 String key = cacheKey.toString();
 207  0
                 Collection<String> principalIds = getRoleMemberPrincipalIdsCache(key);
 208  0
                 if (principalIds != null) {
 209  0
                         return principalIds;
 210  
                 }
 211  0
                 principalIds = getRoleService().getRoleMemberPrincipalIds(namespaceCode, roleName, qualification);
 212  0
                 addRoleMemberPrincipalIdsToCache(key, principalIds);
 213  0
                 return principalIds;
 214  
         }
 215  
 
 216  
         /**
 217  
          * @see org.kuali.rice.kim.service.RoleService#getRole(java.lang.String)
 218  
          */
 219  
         public KimRoleInfo getRole(String roleId) {
 220  0
                 KimRoleInfo role = getRoleByIdCache(roleId);
 221  0
                 if (role != null) {
 222  0
                         return role;
 223  
                 }
 224  0
                 role = getRoleService().getRole(roleId);
 225  0
                 addRoleToCaches(role);
 226  0
             return role;
 227  
         }
 228  
 
 229  
         /**
 230  
          * @see org.kuali.rice.kim.service.RoleService#getRoleByName(java.lang.String, java.lang.String)
 231  
          */
 232  
         public KimRoleInfo getRoleByName(String namespaceCode, String roleName) {
 233  0
                 KimRoleInfo role = getRoleByNameCache(namespaceCode + "-" + roleName);
 234  0
                 if (role != null) {
 235  0
                         return role;
 236  
                 }
 237  0
                 role = getRoleService().getRoleByName(namespaceCode, roleName);
 238  0
                 addRoleToCaches(role);
 239  0
             return role;
 240  
         }
 241  
 
 242  
         /**
 243  
          * @see org.kuali.rice.kim.service.RoleService#getRoleIdByName(java.lang.String, java.lang.String)
 244  
          */
 245  
         public String getRoleIdByName(String namespaceCode, String roleName) {
 246  0
                 KimRoleInfo role = getRoleByName( namespaceCode, roleName );
 247  0
                 if ( role == null ) {
 248  0
                         return null;
 249  
                 }
 250  0
                 return role.getRoleId();
 251  
         }
 252  
                 
 253  
         /**
 254  
          * @see org.kuali.rice.kim.service.RoleService#getRoles(java.util.List)
 255  
          */
 256  
         public List<KimRoleInfo> getRoles(List<String> roleIds) {
 257  0
                 return getRoleService().getRoles(roleIds);
 258  
         }
 259  
 
 260  
         protected void addIdsToKey( StringBuffer key, List<String> idList ) {
 261  0
                 if ( idList == null || idList.isEmpty() ) {
 262  0
                         key.append( "[null]" );
 263  
                 } else {
 264  0
                         for ( String id : idList ) {
 265  0
                                 key.append( '|' ).append( id ).append( '|' );
 266  
                         }
 267  
                 }
 268  0
         }
 269  
         
 270  
         protected void addAttributesToKey( StringBuffer key, AttributeSet attributes ) {
 271  0
                 if ( attributes == null || attributes.isEmpty() ) {
 272  0
                         key.append( "[null]" );
 273  
                 } else {
 274  0
                         for (Map.Entry<String, String> entry : attributes.entrySet()) {
 275  0
                                 key.append( entry.getKey() ).append( '=' ).append( entry.getValue() ).append( '|' );
 276  
                         }
 277  
                 }
 278  0
         }
 279  
 
 280  
         /**
 281  
          * @see org.kuali.rice.kim.service.RoleService#getRoleMembers(java.util.List, org.kuali.rice.core.util.AttributeSet)
 282  
          */
 283  
         public List<RoleMembershipInfo> getRoleMembers(List<String> roleIds, AttributeSet qualification) {
 284  0
                 List<String>[] filteredRoles = filterRoleIdsByCachingAbility(roleIds);
 285  0
                 List<String> cacheRoles = filteredRoles[0];
 286  0
                 List<String> noCacheRoles = filteredRoles[1];
 287  
                 
 288  0
                 List<RoleMembershipInfo> members = null;
 289  0
                 String key = null;
 290  
                 
 291  0
                 if (!cacheRoles.isEmpty()) {
 292  0
                         StringBuffer cacheKey = new StringBuffer();
 293  0
                         addIdsToKey( cacheKey, cacheRoles );
 294  0
                         cacheKey.append(  '/' );
 295  0
                         addAttributesToKey( cacheKey, qualification );
 296  0
                         key = cacheKey.toString();
 297  0
                         members = getRoleMembersWithDelegationCache(key);
 298  
                 }
 299  0
                 if (members != null) {
 300  0
                         if (!noCacheRoles.isEmpty()) {
 301  0
                                 members.addAll(getRoleService().getRoleMembers(noCacheRoles, qualification));
 302  
                         }
 303  0
                         return members;
 304  
                 }
 305  
                 
 306  0
                 if (!cacheRoles.isEmpty()) {
 307  0
                         members = getRoleService().getRoleMembers(cacheRoles, qualification);
 308  0
                         addRoleMembersWithDelegationToCache(key, members);
 309  
                 } else {
 310  0
                         members = new ArrayList<RoleMembershipInfo>();
 311  
                 }
 312  0
                 if (!noCacheRoles.isEmpty()) {
 313  0
                         members.addAll(getRoleService().getRoleMembers(noCacheRoles, qualification));
 314  
                 }
 315  0
             return members;
 316  
     }
 317  
 
 318  
         /**
 319  
          * @see org.kuali.rice.kim.service.RoleService#getRoleQualifiersForPrincipal(java.lang.String, java.util.List, org.kuali.rice.core.util.AttributeSet)
 320  
          */
 321  
         public List<AttributeSet> getRoleQualifiersForPrincipal(String principalId, List<String> roleIds, AttributeSet qualification) {                
 322  0
                 StringBuffer cacheKey = new StringBuffer( principalId );
 323  0
                 cacheKey.append( '/' );
 324  0
                 addIdsToKey( cacheKey, roleIds );
 325  0
                 cacheKey.append(  '/' );
 326  0
                 addAttributesToKey( cacheKey, qualification );
 327  0
                 String key = cacheKey.toString();
 328  0
                 List<AttributeSet> qualifiers = getRoleQualifiersForPrincipalCache(key);
 329  0
                 if (qualifiers != null) {
 330  0
                         return qualifiers;
 331  
                 }
 332  0
                 qualifiers = getRoleService().getRoleQualifiersForPrincipal(principalId, roleIds, qualification);
 333  0
                 addRoleQualifiersForPrincipalToCache(key, qualifiers);
 334  0
             return qualifiers;
 335  
         }
 336  
 
 337  
         /**
 338  
          * @see org.kuali.rice.kim.service.RoleService#getRoleQualifiersForPrincipal(java.lang.String, java.lang.String, java.lang.String, org.kuali.rice.core.util.AttributeSet)
 339  
          */
 340  
         public List<AttributeSet> getRoleQualifiersForPrincipal(String principalId, String namespaceCode, String roleName, AttributeSet qualification) {
 341  0
                 StringBuffer cacheKey = new StringBuffer( principalId );
 342  0
                 cacheKey.append( '/' );
 343  0
                 cacheKey.append( namespaceCode ).append( '-' ).append( roleName );
 344  0
                 cacheKey.append( '/' );
 345  0
                 addAttributesToKey( cacheKey, qualification );
 346  0
                 String key = cacheKey.toString();
 347  0
                 List<AttributeSet> qualifiers = getRoleQualifiersForPrincipalCache(key);
 348  0
                 if (qualifiers != null) {
 349  0
                         return qualifiers;
 350  
                 }
 351  0
                 qualifiers = getRoleService().getRoleQualifiersForPrincipal(principalId, namespaceCode, roleName, qualification);
 352  0
                 addRoleQualifiersForPrincipalToCache(key, qualifiers);
 353  0
             return qualifiers;
 354  
         }
 355  
 
 356  
         public boolean isRoleActive(String roleId) {
 357  0
                 KimRoleInfo role = getRole( roleId );
 358  0
                 return role != null && role.isActive();
 359  
         }
 360  
 
 361  
         public boolean principalHasRole(String principalId, List<String> roleIds, AttributeSet qualification) {
 362  0
                 if ( LOG.isDebugEnabled() ) {
 363  0
                         logPrincipalHasRoleCheck(principalId, roleIds, qualification);
 364  
                 }
 365  0
                 List<String>[] filteredRoles = filterRoleIdsByCachingAbility(roleIds);
 366  0
                 List<String> cacheRoles = filteredRoles[0];
 367  0
                 List<String> noCacheRoles = filteredRoles[1];
 368  
                 
 369  0
                 Boolean hasRole = null;
 370  0
                 String key = null;
 371  0
                 if (!cacheRoles.isEmpty()) {
 372  0
                         StringBuffer cacheKey = new StringBuffer();
 373  0
                         cacheKey.append( principalId );
 374  0
                         cacheKey.append( '/' );
 375  0
                         addIdsToKey( cacheKey, cacheRoles );
 376  0
                         cacheKey.append( '/' );
 377  0
                         addAttributesToKey( cacheKey, qualification );
 378  0
                         key = cacheKey.toString();
 379  0
                         hasRole = getPrincipalHasRoleCacheCache(key);
 380  
                 }
 381  0
                 if (hasRole == null || !hasRole.booleanValue()) {
 382  0
                         if (!cacheRoles.isEmpty()) {
 383  0
                                 hasRole = getRoleService().principalHasRole(principalId, cacheRoles, qualification);
 384  0
                                 addPrincipalHasRoleToCache(key, hasRole);
 385  
                         }
 386  0
                         if ((hasRole == null || !hasRole.booleanValue()) && !noCacheRoles.isEmpty()) {
 387  0
                                 hasRole = getRoleService().principalHasRole(principalId, noCacheRoles, qualification);
 388  
                         }
 389  0
                     if ( LOG.isDebugEnabled() ) {
 390  0
                             LOG.debug( "Result: " + hasRole );
 391  
                     }
 392  
                 } else {
 393  0
                         if ( LOG.isDebugEnabled() ) {
 394  0
                                 LOG.debug( "Result Found in cache using key: " + key + "\nResult: " + hasRole );
 395  
                         }
 396  
                 }
 397  0
             return hasRole;
 398  
         }
 399  
         
 400  
         /**
 401  
          * Determines if the role with the given id will be cached
 402  
          * 
 403  
          * @param roleId the role id of the role to determine caching on
 404  
          * @return true if the role should be cached, false otherwise
 405  
          */
 406  
         protected boolean shouldCacheRole(String roleId) {
 407  0
                 Boolean shouldCacheRoleAnswer = shouldCacheRoleCache.get(roleId);
 408  0
                 if (shouldCacheRoleAnswer == null) {
 409  
                 
 410  0
                         final KimRoleTypeService roleType = getRoleTypeService(roleId);
 411  0
                         final KimRoleInfo roleInfo = this.getRole(roleId);
 412  0
                         if (roleType != null && roleInfo != null) {
 413  
                             try {
 414  0
                                 shouldCacheRoleAnswer = new Boolean(roleType.shouldCacheRoleMembershipResults(roleInfo.getNamespaceCode(), roleInfo.getRoleName()));
 415  0
                                 shouldCacheRoleCache.put(roleId, shouldCacheRoleAnswer);
 416  0
                             } catch (Exception e) {//was: RiceRemoteServiceConnectionException
 417  0
                                 LOG.warn("Unable to connect to remote service for roleType " + roleInfo.getNamespaceCode() + "-" + roleInfo.getRoleName());
 418  0
                     LOG.warn(e.getMessage());
 419  0
                                 return Boolean.FALSE;
 420  0
                             }
 421  
                         } else {
 422  0
                                 shouldCacheRoleAnswer = Boolean.TRUE; // no type?  that means we get to do the default - cache
 423  0
                                 shouldCacheRoleCache.put(roleId, shouldCacheRoleAnswer);
 424  
                         }
 425  
                 }
 426  0
                 return shouldCacheRoleAnswer.booleanValue();
 427  
         }
 428  
         
 429  
         /**
 430  
          * Splits the given List of role ids into two Lists, one with roles to cache, and one with roles
 431  
          * not to cache
 432  
          * 
 433  
          * @param roleIds the List of role ids to split
 434  
          * @return an array of two Lists of role ids - the first, roles which can be cached and the second, roles which should not be cached
 435  
          */
 436  
         @SuppressWarnings("unchecked")
 437  
         protected List<String>[] filterRoleIdsByCachingAbility(List<String> roleIds) {
 438  0
                 List<String> cacheRoles = new ArrayList<String>();
 439  0
                 List<String> noCacheRoles = new ArrayList<String>();
 440  0
                 Set<String> alreadyFilteredRoles = new HashSet<String>();
 441  
                 
 442  0
                 for (String roleId : roleIds) {
 443  0
                         if (!alreadyFilteredRoles.contains(roleId)) {
 444  0
                                 alreadyFilteredRoles.add(roleId);
 445  0
                                 if (shouldCacheRole(roleId)) {
 446  0
                                         cacheRoles.add(roleId);
 447  
                                 } else {
 448  0
                                         noCacheRoles.add(roleId);
 449  
                                 }
 450  
                         }
 451  
                 }
 452  0
                 return (List<String>[])new List[] { cacheRoles, noCacheRoles };
 453  
         }
 454  
         
 455  
         /**
 456  
      * Retrieves the role type service associated with the given role ID
 457  
      * 
 458  
      * @param roleId the role ID to get the role type service for
 459  
      * @return the Role Type Service
 460  
      */
 461  
     protected KimRoleTypeService getRoleTypeService( String roleId ) {
 462  0
             KimRoleTypeService service = null;
 463  
                     
 464  0
             final KimRoleInfo roleInfo = getRoleService().getRole(roleId);
 465  0
             if (roleInfo != null) {
 466  0
                     final KimType roleType = getTypeInfoService().getKimType(roleInfo.getKimTypeId());
 467  0
                     if ( roleType != null ) {
 468  0
                         service = getRoleTypeService(roleType);
 469  
                     }
 470  
             }
 471  0
             return service;
 472  
     }
 473  
 
 474  
         /**
 475  
          * Retrieves a role type from the given type info
 476  
          * 
 477  
          * @param typeInfo
 478  
          * @return
 479  
          */
 480  
         protected KimRoleTypeService getRoleTypeService( KimType typeInfo ) {
 481  0
                 String serviceName = typeInfo.getServiceName();
 482  0
                 if ( serviceName != null ) {
 483  
                         try {
 484  0
                                 KimTypeService service = (KimTypeService) KIMServiceLocatorInternal.getService(serviceName);
 485  0
                                 if ( service != null && service instanceof KimRoleTypeService) {
 486  0
                                         return (KimRoleTypeService)service;
 487  
                                 } else {
 488  0
                                         return (KimRoleTypeService) KIMServiceLocatorInternal.getService("kimNoMembersRoleTypeService");
 489  
                                 }
 490  0
                         } catch ( Exception ex ) {
 491  0
                                 LOG.error( "Unable to find role type service with name: " + serviceName, ex);
 492  0
                                 return (KimRoleTypeService) KIMServiceLocatorInternal.getService("kimNoMembersRoleTypeService");
 493  
                         }
 494  
                 }
 495  0
                 return null;
 496  
         }
 497  
 
 498  
         /**
 499  
          * @see org.kuali.rice.kim.service.RoleService#getPrincipalIdSubListWithRole(java.util.List, java.lang.String, java.lang.String, org.kuali.rice.core.util.AttributeSet)
 500  
          */
 501  
         public List<String> getPrincipalIdSubListWithRole(
 502  
                         List<String> principalIds, String roleNamespaceCode,
 503  
                         String roleName, AttributeSet qualification) {
 504  0
                 return getRoleService().getPrincipalIdSubListWithRole(principalIds,
 505  
                                 roleNamespaceCode, roleName, qualification);
 506  
         }
 507  
 
 508  
         
 509  
 
 510  
         // Helper methods
 511  
         
 512  
         public void removeCacheEntries( String roleId, String principalId ) {
 513  0
                 if ( principalId != null ) {
 514  0
                         String keyPrefix = principalId + "-";
 515  0
                         synchronized ( principalHasRoleCache ) {
 516  0
                                 Iterator<String> cacheIterator = principalHasRoleCache.keySet().iterator();
 517  0
                                 while ( cacheIterator.hasNext() ) {
 518  0
                                         String cacheKey = cacheIterator.next();
 519  0
                                         if ( cacheKey.startsWith( keyPrefix ) ) {
 520  0
                                                 cacheIterator.remove();
 521  
                                         }
 522  0
                                 }
 523  0
                         }
 524  0
                         synchronized ( roleQualifiersForPrincipalCache ) {
 525  0
                                 Iterator<String> cacheIterator = roleQualifiersForPrincipalCache.keySet().iterator();
 526  0
                                 while ( cacheIterator.hasNext() ) {
 527  0
                                         String cacheKey = cacheIterator.next();
 528  0
                                         if ( cacheKey.startsWith( keyPrefix ) ) {
 529  0
                                                 cacheIterator.remove();
 530  
                                         }
 531  0
                                 }
 532  0
                         }
 533  
                 }
 534  0
                 if ( roleId != null ) {
 535  0
                         roleByIdCache.remove( roleId );
 536  0
                         roleByNameCache.clear();
 537  0
                         String keySubstring = "|" + roleId + "|";
 538  0
                         synchronized ( principalHasRoleCache ) {
 539  0
                                 Iterator<String> cacheIterator = principalHasRoleCache.keySet().iterator();
 540  0
                                 while ( cacheIterator.hasNext() ) {
 541  0
                                         String cacheKey = cacheIterator.next();
 542  0
                                         if( cacheKey.contains( keySubstring ) ) {
 543  0
                                                 cacheIterator.remove();
 544  
                                         }
 545  0
                                 }
 546  0
                         }
 547  0
                         synchronized ( roleQualifiersForPrincipalCache ) {
 548  0
                                 Iterator<String> cacheIterator = roleQualifiersForPrincipalCache.keySet().iterator();
 549  0
                                 while ( cacheIterator.hasNext() ) {
 550  0
                                         String cacheKey = cacheIterator.next();
 551  0
                                         if( cacheKey.contains( keySubstring ) ) {
 552  0
                                                 cacheIterator.remove();
 553  
                                         }
 554  0
                                 }
 555  0
                         }
 556  0
                         synchronized ( roleMembersWithDelegationCache ) {
 557  0
                                 Iterator<String> cacheIterator = roleMembersWithDelegationCache.keySet().iterator();
 558  0
                                 while ( cacheIterator.hasNext() ) {
 559  0
                                         String cacheKey = cacheIterator.next();
 560  0
                                         if( cacheKey.contains( keySubstring ) ) {
 561  0
                                                 cacheIterator.remove();
 562  
                                         }
 563  0
                                 }
 564  0
                         }
 565  0
                         synchronized ( memberPrincipalIdsCache ) {
 566  0
                                 Iterator<String> cacheIterator = memberPrincipalIdsCache.keySet().iterator();
 567  0
                                 while ( cacheIterator.hasNext() ) {
 568  0
                                         String cacheKey = cacheIterator.next();
 569  0
                                         if( cacheKey.contains( keySubstring ) ) {
 570  0
                                                 cacheIterator.remove();
 571  
                                         }
 572  0
                                 }
 573  0
                         }
 574  0
                         shouldCacheRoleCache.remove(roleId);
 575  
                 }
 576  0
         }
 577  
         
 578  
         /**
 579  
          * @see org.kuali.rice.kim.service.RoleService#getRoleQualifiersForPrincipalIncludingNested(java.lang.String, java.util.List, org.kuali.rice.core.util.AttributeSet)
 580  
          */
 581  
         public List<AttributeSet> getRoleQualifiersForPrincipalIncludingNested(
 582  
                         String principalId, List<String> roleIds, AttributeSet qualification) {
 583  0
                 return getRoleService().getRoleQualifiersForPrincipalIncludingNested(principalId, roleIds, qualification);
 584  
         }
 585  
         
 586  
         /**
 587  
          * @see org.kuali.rice.kim.service.RoleService#getRoleQualifiersForPrincipalIncludingNested(java.lang.String, java.lang.String, java.lang.String, org.kuali.rice.core.util.AttributeSet)
 588  
          */
 589  
         public List<AttributeSet> getRoleQualifiersForPrincipalIncludingNested(
 590  
                         String principalId, String namespaceCode, String roleName,
 591  
                         AttributeSet qualification) {
 592  0
                 return getRoleService().getRoleQualifiersForPrincipalIncludingNested(principalId, namespaceCode, roleName, qualification);
 593  
         }
 594  
         
 595  
         public void assignGroupToRole(String groupId, String namespaceCode, String roleName,
 596  
                         AttributeSet qualifications) {
 597  0
                 getRoleUpdateService().assignGroupToRole( groupId, namespaceCode, roleName, qualifications );
 598  0
                 KimRoleInfo role = getRoleByName( namespaceCode, roleName );
 599  0
                 removeCacheEntries( role.getRoleId(), null );
 600  0
         }
 601  
 
 602  
         public void assignPrincipalToRole(String principalId, String namespaceCode, String roleName,
 603  
                         AttributeSet qualifications) {
 604  0
                 KimRoleInfo role = getRoleByName( namespaceCode, roleName );
 605  0
                 getRoleUpdateService().assignPrincipalToRole( principalId, namespaceCode, roleName, qualifications );
 606  0
                 removeCacheEntries( role.getRoleId(), principalId );
 607  0
         }
 608  
 
 609  
         public void removeGroupFromRole(String groupId, String namespaceCode, String roleName,
 610  
                         AttributeSet qualifications) {
 611  0
                 getRoleUpdateService().removeGroupFromRole( groupId, namespaceCode, roleName, qualifications );
 612  0
                 KimRoleInfo role = getRoleByName( namespaceCode, roleName );
 613  0
                 removeCacheEntries( role.getRoleId(), null );
 614  0
         }
 615  
 
 616  
         public void removePrincipalFromRole(String principalId, String namespaceCode, String roleName,
 617  
                         AttributeSet qualifications) {
 618  0
                 KimRoleInfo role = getRoleByName( namespaceCode, roleName );
 619  0
                 getRoleUpdateService().removePrincipalFromRole( principalId, namespaceCode, roleName, qualifications );
 620  0
                 removeCacheEntries( role.getRoleId(), principalId );
 621  0
         }
 622  
 
 623  
         /**
 624  
          * @see org.kuali.rice.kim.service.RoleService#getRolesSearchResults(java.util.Map)
 625  
          */
 626  
         public List<? extends Role> getRolesSearchResults(
 627  
                         Map<String, String> fieldValues) {
 628  0
                 return getRoleService().getRolesSearchResults(fieldValues);
 629  
         }
 630  
 
 631  
     protected void logPrincipalHasRoleCheck(String principalId, List<String> roleIds, AttributeSet roleQualifiers ) {
 632  0
                 StringBuilder sb = new StringBuilder();
 633  0
                 sb.append(  '\n' );
 634  0
                 sb.append( "Has Role     : " ).append( roleIds ).append( '\n' );
 635  0
                 if ( roleIds != null ) {
 636  0
                         for ( String roleId : roleIds ) {
 637  0
                                 KimRoleInfo role = getRole( roleId );
 638  0
                                 if ( role != null ) {
 639  0
                                         sb.append( "        Name : " ).append( role.getNamespaceCode() ).append( '/').append( role.getRoleName() );
 640  0
                                         sb.append( " (" ).append( roleId ).append( ')' );
 641  0
                                         sb.append( '\n' );
 642  
                                 }
 643  0
                         }
 644  
                 }
 645  0
                 sb.append( "   Principal : " ).append( principalId );
 646  0
                 if ( principalId != null ) {
 647  0
                         Principal principal = KimApiServiceLocator.getIdentityManagementService().getPrincipal( principalId );
 648  0
                         if ( principal != null ) {
 649  0
                                 sb.append( " (" ).append( principal.getPrincipalName() ).append( ')' );
 650  
                         }
 651  
                 }
 652  0
                 sb.append( '\n' );
 653  0
                 sb.append( "     Details :\n" );
 654  0
                 if ( roleQualifiers != null ) {
 655  0
                         sb.append( roleQualifiers.formattedDump( 15 ) );
 656  
                 } else {
 657  0
                         sb.append( "               [null]\n" );
 658  
                 }
 659  0
                 if (LOG.isTraceEnabled()) { 
 660  0
                         LOG.trace( sb.append(ExceptionUtils.getStackTrace(new Throwable())));
 661  
                 } else {
 662  0
                         LOG.debug(sb.toString());
 663  
                 }
 664  0
     }
 665  
 
 666  
     /**
 667  
      * @see org.kuali.rice.kim.service.RoleService#principalInactivated(java.lang.String)
 668  
      */
 669  
     public void principalInactivated(String principalId) {
 670  0
             getRoleService().principalInactivated(principalId);    
 671  0
             removeCacheEntries(null, principalId);
 672  0
     }
 673  
     
 674  
     /**
 675  
      * @see org.kuali.rice.kim.service.RoleService#roleInactivated(java.lang.String)
 676  
      */
 677  
     public void roleInactivated(String roleId) {
 678  0
             getRoleService().roleInactivated(roleId);    
 679  0
             removeCacheEntries(roleId, null);
 680  0
     }
 681  
     
 682  
     /**
 683  
      * @see org.kuali.rice.kim.service.RoleService#roleInactivated(java.lang.String)
 684  
      */
 685  
     public void groupInactivated(String groupId) {
 686  0
             getRoleService().groupInactivated(groupId);    
 687  0
     }
 688  
 
 689  
     public List<RoleMembershipInfo> getFirstLevelRoleMembers(List<String> roleIds){
 690  0
             return getRoleService().getFirstLevelRoleMembers(roleIds);
 691  
     }
 692  
 
 693  
     public List<RoleMembershipInfo> findRoleMembers(Map<String, String> fieldValues){
 694  0
             return getRoleService().findRoleMembers(fieldValues);
 695  
     }
 696  
 
 697  
         public void assignRoleToRole(String roleId, String namespaceCode, String roleName,
 698  
                         AttributeSet qualifications) {
 699  0
                 getRoleUpdateService().assignRoleToRole( 
 700  
                                 roleId, namespaceCode, roleName, qualifications);
 701  0
                 KimRoleInfo role = getRoleByName( namespaceCode, roleName );
 702  0
                 removeCacheEntries( role.getRoleId(), null );
 703  0
         }
 704  
 
 705  
     /**
 706  
      * @see org.kuali.rice.kim.service.RoleUpdateService#assignRoleAsDelegationMemberToRole(java.lang.String, java.lang.String, java.lang.String, org.kuali.rice.core.util.AttributeSet)
 707  
      */
 708  
         public void saveDelegationMemberForRole(String delegationMemberId, String roleMemberId, String memberId, String memberTypeCode, 
 709  
                         String delegationTypeCode, String roleId, AttributeSet qualifications, 
 710  
                         Date activeFromDate, Date activeToDate) throws UnsupportedOperationException{
 711  0
             getRoleUpdateService().saveDelegationMemberForRole(delegationMemberId, roleMemberId, memberId, memberTypeCode, delegationTypeCode, roleId, qualifications, activeFromDate, activeToDate);
 712  0
                 KimRoleInfo role = getRole( roleId );
 713  0
                 removeCacheEntries( role.getRoleId(), null );
 714  0
     }
 715  
 
 716  
     public RoleMemberCompleteInfo saveRoleMemberForRole(String roleMemberId, String memberId, String memberTypeCode, 
 717  
                     String roleId, AttributeSet qualifications, Date activeFromDate, Date activeToDate) throws UnsupportedOperationException{
 718  0
                 KimRoleInfo role = getRole( roleId );
 719  0
                 RoleMemberCompleteInfo roleMemberCompleteInfo = getRoleUpdateService().saveRoleMemberForRole(roleMemberId, memberId, memberTypeCode, roleId, qualifications, activeFromDate, activeToDate);
 720  0
                 removeCacheEntries( role.getRoleId(), memberId );
 721  0
                 return roleMemberCompleteInfo;
 722  
     }
 723  
     
 724  
         public void removeRoleFromRole(String roleId, String namespaceCode, String roleName,
 725  
                         AttributeSet qualifications) {
 726  0
                 getRoleUpdateService().removeRoleFromRole( roleId, namespaceCode, roleName, qualifications );
 727  0
                 KimRoleInfo role = getRoleByName( namespaceCode, roleName );
 728  0
                 removeCacheEntries( role.getRoleId(), null );
 729  0
         }
 730  
 
 731  
     public List<RoleMemberCompleteInfo> findRoleMembersCompleteInfo(Map<String, String> fieldValues){
 732  0
             return getRoleService().findRoleMembersCompleteInfo(fieldValues);
 733  
     }
 734  
     
 735  
     public List<DelegateMemberCompleteInfo> findDelegateMembersCompleteInfo(Map<String, String> fieldValues){
 736  0
             return getRoleService().findDelegateMembersCompleteInfo(fieldValues);
 737  
     }
 738  
         
 739  
     public List<DelegateMemberCompleteInfo> getDelegationMembersByDelegationId(@WebParam(name="delegationId") String delegationId){
 740  0
                 return getRoleService().getDelegationMembersByDelegationId(delegationId);
 741  
         }
 742  
         
 743  
         public DelegateMemberCompleteInfo getDelegationMemberByDelegationAndMemberId(@WebParam(name="delegationId") String delegationId, @WebParam(name="memberId") String memberId){
 744  0
                 return getRoleService().getDelegationMemberByDelegationAndMemberId(delegationId, memberId);
 745  
         }
 746  
         
 747  
         public DelegateMemberCompleteInfo getDelegationMemberById(@WebParam(name="delegationMemberId") String delegationMemberId){
 748  0
                 return getRoleService().getDelegationMemberById(delegationMemberId);        
 749  
         }
 750  
 
 751  
         public List<RoleResponsibilityActionInfo> getRoleMemberResponsibilityActionInfo(String roleMemberId){
 752  0
                 return getRoleService().getRoleMemberResponsibilityActionInfo(roleMemberId);
 753  
         }
 754  
         
 755  
         public DelegateTypeInfo getDelegateTypeInfo(String roleId, String delegationTypeCode){
 756  0
                 return getRoleService().getDelegateTypeInfo(roleId, delegationTypeCode);
 757  
         }
 758  
 
 759  
         public DelegateTypeInfo getDelegateTypeInfoById(String delegationId){
 760  0
                 return getRoleService().getDelegateTypeInfoById(delegationId);
 761  
         }
 762  
         
 763  
         public void saveRoleRspActions(String roleResponsibilityActionId, String roleId, String roleResponsibilityId, String roleMemberId, 
 764  
                         String actionTypeCode, String actionPolicyCode, Integer priorityNumber, Boolean forceAction){
 765  0
             getRoleUpdateService().saveRoleRspActions(roleResponsibilityActionId, roleId, roleResponsibilityId, roleMemberId, actionTypeCode, actionPolicyCode, priorityNumber, forceAction);
 766  0
                 removeCacheEntries(roleId, null);
 767  0
         }
 768  
 
 769  
         public List<RoleResponsibilityInfo> getRoleResponsibilities(String roleId){
 770  0
                 return getRoleService().getRoleResponsibilities(roleId);
 771  
         }
 772  
         
 773  
         public void applicationRoleMembershipChanged(String roleId) {
 774  0
                 removeCacheEntries(roleId, null);
 775  0
                 getRoleService().applicationRoleMembershipChanged(roleId);                
 776  0
         }
 777  
         
 778  
         // Spring and injection methods
 779  
         
 780  
         public RoleService getRoleService() {
 781  0
                 if ( roleService == null ) {
 782  0
                         roleService = KimApiServiceLocator.getRoleService();
 783  
                 }
 784  0
                 return roleService;
 785  
         }
 786  
         
 787  
         public KimTypeInfoService getTypeInfoService() {
 788  0
                 if (typeInfoService == null) {
 789  0
                         typeInfoService = KimApiServiceLocator.getKimTypeInfoService();
 790  
                 }
 791  0
                 return typeInfoService;
 792  
         }
 793  
 
 794  
         public RoleUpdateService getRoleUpdateService() {
 795  
                 try {
 796  0
                         if ( roleUpdateService == null ) {
 797  0
                                 roleUpdateService = KimApiServiceLocator.getRoleUpdateService();
 798  0
                                 if ( roleUpdateService == null ) {
 799  0
                                         throw new UnsupportedOperationException( "null returned for RoleUpdateService, unable to update role data");
 800  
                                 }
 801  
                         }
 802  0
                 } catch ( Exception ex ) {
 803  0
                         throw new UnsupportedOperationException( "unable to obtain a RoleUpdateService, unable to update role data", ex);
 804  0
                 }
 805  0
                 return roleUpdateService;
 806  
         }
 807  
         
 808  
         public void setRoleCacheMaxSize(int roleCacheMaxSize) {
 809  0
                 this.roleCacheMaxSize = roleCacheMaxSize;
 810  0
         }
 811  
 
 812  
         public void setRoleCacheMaxAgeSeconds(int roleCacheMaxAge) {
 813  0
                 this.roleCacheMaxAgeSeconds = roleCacheMaxAge;
 814  0
         }
 815  
         
 816  
         /**
 817  
          * This overridden method looks up roles based on criteria.  If you want
 818  
          * to return all roles pass in an empty map.
 819  
          *
 820  
          * @see org.kuali.rice.kim.service.RoleService#lookupRoles(java.util.Map)
 821  
          */
 822  
         public List<KimRoleInfo> lookupRoles(Map<String, String> searchCriteria) {
 823  0
                 return getRoleService().lookupRoles(searchCriteria);
 824  
         }
 825  
 
 826  
         public void flushInternalRoleCache() {
 827  0
                 getRoleService().flushInternalRoleCache();
 828  0
         }
 829  
         
 830  
         public void flushInternalRoleMemberCache() {
 831  0
                 getRoleService().flushInternalRoleMemberCache();
 832  0
         }
 833  
         
 834  
         public void flushInternalDelegationCache() {
 835  0
                 getRoleService().flushInternalDelegationCache();
 836  0
         }
 837  
         
 838  
         public void flushInternalDelegationMemberCache() {
 839  0
                 getRoleService().flushInternalDelegationMemberCache();
 840  0
         }
 841  
 
 842  
     public void assignPermissionToRole(String permissionId, String roleId) throws UnsupportedOperationException {
 843  0
         getRoleUpdateService().assignPermissionToRole(permissionId, roleId);
 844  0
     }
 845  
 
 846  
     public String getNextAvailableRoleId() throws UnsupportedOperationException {
 847  0
         return getRoleUpdateService().getNextAvailableRoleId();
 848  
     }
 849  
 
 850  
     public void saveRole(String roleId, String roleName, String roleDescription, boolean active, String kimTypeId, String namespaceCode) throws UnsupportedOperationException {
 851  0
         getRoleUpdateService().saveRole(roleId, roleName, roleDescription, active, kimTypeId, namespaceCode);
 852  0
     }
 853  
 
 854  
         /**
 855  
          * This overridden method ...
 856  
          * 
 857  
          * @see org.kuali.rice.kim.service.RoleService#getMemberParentRoleIds(java.lang.String, java.lang.String)
 858  
          */
 859  
         public List<String> getMemberParentRoleIds(String memberType,
 860  
                         String memberId) {
 861  0
                 return getRoleService().getMemberParentRoleIds(memberType, memberId);
 862  
         }
 863  
 }