View Javadoc

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.StringUtils;
19  import org.apache.log4j.Logger;
20  import org.kuali.rice.core.api.config.property.ConfigContext;
21  import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
22  import org.kuali.rice.kim.api.permission.Permission;
23  import org.kuali.rice.kim.api.role.Role;
24  import org.kuali.rice.kim.api.role.RoleMembership;
25  import org.kuali.rice.kim.api.role.RoleService;
26  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
27  import org.kuali.rice.kim.api.type.KimAttributeField;
28  import org.kuali.rice.kim.api.type.KimType;
29  import org.kuali.rice.kim.bo.impl.PermissionImpl;
30  import org.kuali.rice.kim.bo.role.dto.KimPermissionInfo;
31  import org.kuali.rice.kim.bo.role.dto.KimPermissionTemplateInfo;
32  import org.kuali.rice.kim.bo.role.dto.PermissionAssigneeInfo;
33  import org.kuali.rice.kim.bo.role.impl.KimPermissionTemplateImpl;
34  import org.kuali.rice.kim.dao.KimPermissionDao;
35  import org.kuali.rice.kim.framework.permission.PermissionTypeService;
36  import org.kuali.rice.kim.impl.permission.PermissionBo;
37  import org.kuali.rice.kim.impl.permission.PermissionTemplateBo;
38  import org.kuali.rice.kim.service.KIMServiceLocatorInternal;
39  import org.kuali.rice.kim.service.PermissionService;
40  import org.kuali.rice.kim.util.KIMWebServiceConstants;
41  import org.kuali.rice.kim.util.KimConstants;
42  import org.kuali.rice.kns.lookup.Lookupable;
43  import org.kuali.rice.kns.service.KNSServiceLocator;
44  import org.kuali.rice.krad.lookup.CollectionIncomplete;
45  import org.kuali.rice.krad.service.BusinessObjectService;
46  import org.kuali.rice.krad.service.DataDictionaryService;
47  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
48  import org.kuali.rice.krad.util.KRADPropertyConstants;
49  
50  import javax.jws.WebService;
51  import java.util.ArrayList;
52  import java.util.Collection;
53  import java.util.Collections;
54  import java.util.Comparator;
55  import java.util.HashMap;
56  import java.util.List;
57  import java.util.Map;
58  
59  /**
60   * This is a description of what this class does - jonathan don't forget to fill this in. 
61   * 
62   * @author Kuali Rice Team (rice.collab@kuali.org)
63   *
64   */
65  @WebService(endpointInterface = KIMWebServiceConstants.PermissionService.INTERFACE_CLASS, serviceName = KIMWebServiceConstants.PermissionService.WEB_SERVICE_NAME, portName = KIMWebServiceConstants.PermissionService.WEB_SERVICE_PORT, targetNamespace = KIMWebServiceConstants.MODULE_TARGET_NAMESPACE)
66  public class PermissionServiceImpl extends PermissionServiceBase implements PermissionService {
67  	private static final Logger LOG = Logger.getLogger( PermissionServiceImpl.class );
68  
69     	private RoleService roleService;
70  	private KimPermissionDao permissionDao;
71      private PermissionTypeService defaultPermissionTypeService;
72  	
73  	private List<KimPermissionTemplateInfo> allTemplates;
74  	
75      // --------------------
76      // Authorization Checks
77      // --------------------
78      
79  	protected PermissionTypeService getPermissionTypeService( String namespaceCode, String permissionTemplateName, String permissionName, String permissionId ) {
80  		StringBuffer cacheKey = new StringBuffer();
81  		if ( namespaceCode != null ) {
82  			cacheKey.append( namespaceCode );
83  		}
84  		cacheKey.append( '|' );
85  		if ( permissionTemplateName != null ) {
86  			cacheKey.append( permissionTemplateName );
87  		}
88  		cacheKey.append( '|' );
89  		if ( permissionName != null ) {
90  			cacheKey.append( permissionName );
91  		}
92  		cacheKey.append( '|' );
93  		if ( permissionId != null ) {
94  			cacheKey.append( permissionId );
95  		}
96  		String key = cacheKey.toString();
97  		PermissionTypeService service = getPermissionTypeServiceByNameCache().get(key);
98  		if ( service == null ) {
99  			PermissionTemplateBo permTemplate = null;
100 			if ( permissionTemplateName != null ) {
101 				List<PermissionBo> perms = getPermissionImplsByTemplateName(namespaceCode, permissionTemplateName);
102                 if ( !perms.isEmpty() ) {
103 					permTemplate = perms.get(0).getTemplate();
104 				}
105 			} else if ( permissionName != null ) {
106 				PermissionBo perms = getPermissionImplsByName(namespaceCode, permissionName);
107 				permTemplate = perms.getTemplate();
108 			} else if ( permissionId != null ) {
109 				PermissionBo perm = getPermissionImpl(permissionId);
110 				if ( perm != null ) {
111 					permTemplate = perm.getTemplate();
112 				}
113 			}
114 			service = getPermissionTypeService( permTemplate );
115 			getPermissionTypeServiceByNameCache().put(key, service);
116 		}
117 		return service;
118 	}
119 
120     protected PermissionTypeService getPermissionTypeService( PermissionTemplateBo permissionTemplate ) {
121     	if ( permissionTemplate == null ) {
122     		throw new IllegalArgumentException( "permissionTemplate may not be null" );
123     	}
124     	KimType kimType = KimApiServiceLocator.getKimTypeInfoService().getKimType( permissionTemplate.getKimTypeId() );
125     	String serviceName = kimType.getServiceName();
126     	// if no service specified, return a default implementation
127     	if ( StringUtils.isBlank( serviceName ) ) {
128     		return getDefaultPermissionTypeService();
129     	}
130     	try {
131 	    	Object service = KIMServiceLocatorInternal.getService(serviceName);
132 	    	// if we have a service name, it must exist
133 	    	if ( service == null ) {
134 				throw new RuntimeException("null returned for permission type service for service name: " + serviceName);
135 	    	}
136 	    	// whatever we retrieved must be of the correct type
137 	    	if ( !(service instanceof PermissionTypeService)  ) {
138 	    		throw new RuntimeException( "Service " + serviceName + " was not a PermissionTypeService.  Was: " + service.getClass().getName() );
139 	    	}
140 	    	return (PermissionTypeService)service;
141     	} catch( Exception ex ) {
142     		// sometimes service locators throw exceptions rather than returning null, handle that
143     		throw new RuntimeException( "Error retrieving service: " + serviceName + " from the KIMServiceLocatorInternal.", ex );
144     	}
145     }
146     
147     protected PermissionTypeService getDefaultPermissionTypeService() {
148     	if ( defaultPermissionTypeService == null ) {
149     		defaultPermissionTypeService = (PermissionTypeService) KIMServiceLocatorInternal.getBean(DEFAULT_PERMISSION_TYPE_SERVICE);
150     	}
151 		return defaultPermissionTypeService;
152 	}
153 	
154     /**
155      * @see org.kuali.rice.kim.service.PermissionService#hasPermission(java.lang.String, String, java.lang.String, Map<String, String>)
156      */
157     public boolean hasPermission(String principalId, String namespaceCode, String permissionName, Map<String, String> permissionDetails) {
158     	return isAuthorized( principalId, namespaceCode, permissionName, permissionDetails, null );
159     }
160 
161     /**
162      * @see org.kuali.rice.kim.service.PermissionService#isAuthorized( java.lang.String, String, java.lang.String, Map<String, String>, Map<String, String>)
163      */
164     public boolean isAuthorized(String principalId, String namespaceCode, String permissionName, Map<String, String> permissionDetails, Map<String, String> qualification ) {
165         if (StringUtils.isEmpty(namespaceCode)) {
166             throw new RiceIllegalArgumentException("namespaceCode is null");
167         }
168 
169         if (StringUtils.isEmpty(permissionName)) {
170             throw new RiceIllegalArgumentException("permissionName is null");
171         }
172 
173         List<String> roleIds = getRoleIdsForPermission( namespaceCode, permissionName, permissionDetails );
174     	if ( roleIds.isEmpty() ) {
175     		return false;
176     	}
177 		return getRoleService().principalHasRole( principalId, roleIds, qualification );
178     }
179 
180     /**
181      * @see org.kuali.rice.kim.service.PermissionService#hasPermission(String, String, String, Map<String, String>)
182      */
183     public boolean hasPermissionByTemplateName(String principalId, String namespaceCode, String permissionTemplateName, Map<String, String> permissionDetails) {
184     	return isAuthorizedByTemplateName( principalId, namespaceCode, permissionTemplateName, permissionDetails, null );
185     }
186 
187     /**
188      * @see org.kuali.rice.kim.service.PermissionService#isAuthorized( java.lang.String, String, java.lang.String, Map<String, String>, Map<String, String>)
189      */
190     public boolean isAuthorizedByTemplateName(String principalId, String namespaceCode, String permissionTemplateName, Map<String, String> permissionDetails, Map<String, String> qualification ) {
191     	if (StringUtils.isEmpty(namespaceCode)) {
192             throw new RiceIllegalArgumentException("namespaceCode is null");
193         }
194 
195         if (StringUtils.isEmpty(permissionTemplateName)) {
196             throw new RiceIllegalArgumentException("permissionTemplateName is null");
197         }
198 
199         List<String> roleIds = getRoleIdsForPermissionTemplate( namespaceCode, permissionTemplateName, permissionDetails );
200     	if ( roleIds.isEmpty() ) {
201     		return false;
202     	}
203     	return getRoleService().principalHasRole( principalId, roleIds, qualification );
204     }
205 
206     /**
207      * @see org.kuali.rice.kim.service.PermissionService#getAuthorizedPermissions(String, String, String, Map<String, String>, Map<String, String>)
208      */
209     public List<Permission> getAuthorizedPermissions(String principalId, String namespaceCode, String permissionName, Map<String, String> permissionDetails, Map<String, String> qualification) {
210     	if (StringUtils.isEmpty(namespaceCode)) {
211             throw new RiceIllegalArgumentException("namespaceCode is null");
212         }
213 
214         if (StringUtils.isEmpty(permissionName)) {
215             throw new RiceIllegalArgumentException("permissionName is null");
216         }
217 
218     	// get all the permission objects whose name match that requested
219     	PermissionBo permissions = getPermissionImplsByName( namespaceCode, permissionName );
220     	// now, filter the full list by the detail passed
221     	List<PermissionBo> applicablePermissions = getMatchingPermissions( Collections.singletonList(permissions), permissionDetails );
222     	List<PermissionBo> permissionsForUser =
223                 getPermissionsForUser(principalId, applicablePermissions, qualification);
224         List<Permission> returnList = new ArrayList<Permission>();
225         for (PermissionBo bo : permissionsForUser) { returnList.add(PermissionBo.to(bo));}
226         return returnList;
227 
228 
229     }
230 
231     /**
232      * @see org.kuali.rice.kim.service.PermissionService#getAuthorizedPermissionsByTemplateName(String, String, String, Map<String, String>, Map<String, String>)
233      */
234     public List<Permission> getAuthorizedPermissionsByTemplateName(String principalId, String namespaceCode, String permissionTemplateName, Map<String, String> permissionDetails, Map<String, String> qualification) {
235     	if (StringUtils.isEmpty(namespaceCode)) {
236             throw new RiceIllegalArgumentException("namespaceCode is null");
237         }
238 
239         if (StringUtils.isEmpty(permissionTemplateName)) {
240             throw new RiceIllegalArgumentException("permissionName is null");
241         }
242 
243     	// get all the permission objects whose name match that requested
244     	List<PermissionBo> permissions = getPermissionImplsByTemplateName( namespaceCode, permissionTemplateName );
245     	// now, filter the full list by the detail passed
246 
247     	List<PermissionBo> applicablePermissions = getMatchingPermissions( permissions, permissionDetails );
248         List<PermissionBo> permissionsForUser = getPermissionsForUser(principalId, applicablePermissions,
249                 qualification);
250         List<Permission> returnList = new ArrayList<Permission>();
251         for (PermissionBo bo : permissionsForUser) { returnList.add(PermissionBo.to(bo)); }
252         return returnList;
253 
254     }
255     
256     /**
257      * Checks the list of permissions against the principal's roles and returns a subset of the list which match.
258      */
259     protected List<PermissionBo> getPermissionsForUser(String principalId, List<PermissionBo> permissions, Map<String, String> qualification) {
260     	ArrayList<PermissionBo> results = new ArrayList<PermissionBo>();
261     	List<PermissionBo> tempList = new ArrayList<PermissionBo>(1);
262     	for ( PermissionBo perm : permissions ) {
263     		tempList.clear();
264     		tempList.add( perm );
265     		List<String> roleIds = permissionDao.getRoleIdsForPermissions( tempList );
266     		// TODO: This could be made a little better by collecting the role IDs into
267     		// a set and then processing the distinct list rather than a check
268     		// for every permission
269     		if ( roleIds != null && !roleIds.isEmpty() ) {
270     			if ( getRoleService().principalHasRole( principalId, roleIds, qualification)) {
271     				results.add( perm );
272     			}
273     		}
274     	}
275     	
276     	return results;    	
277     }
278 
279     protected Map<String,PermissionTypeService> getPermissionTypeServicesByTemplateId( Collection<PermissionBo> permissions ) {
280     	Map<String,PermissionTypeService> permissionTypeServices = new HashMap<String, PermissionTypeService>( permissions.size() );
281     	for ( PermissionBo perm : permissions ) {
282     		permissionTypeServices.put(perm.getTemplateId(), getPermissionTypeService( perm.getTemplate() ) );    				
283     	}
284     	return permissionTypeServices;
285     }
286     
287     protected Map<String, List<PermissionBo>> groupPermissionsByTemplate(Collection<PermissionBo> permissions) {
288     	Map<String, List<PermissionBo>> results = new HashMap<String, List<PermissionBo>>();
289     	for ( PermissionBo perm : permissions ) {
290     		List<PermissionBo> perms = results.get(perm.getTemplateId());
291     		if ( perms == null ) {
292     			perms = new ArrayList<PermissionBo>();
293     			results.put( perm.getTemplateId(), perms );
294     		}
295     		perms.add( perm);
296     	}
297     	return results;
298     }
299     
300 	/**
301      * Compare each of the passed in permissions with the given permissionDetails.  Those that
302      * match are added to the result list.
303      */
304     protected List<PermissionBo> getMatchingPermissions(List<PermissionBo> permissions, Map<String, String> permissionDetails) {
305     	List<PermissionBo> applicablePermissions = new ArrayList<PermissionBo>();
306     	if ( permissionDetails == null || permissionDetails.isEmpty() ) {
307     		// if no details passed, assume that all match
308     		for ( PermissionBo perm : permissions ) {
309     			if (perm != null) {
310                     applicablePermissions.add( perm );
311                 }
312     		}
313     	} else {
314     		// otherwise, attempt to match the permission details
315     		// build a map of the template IDs to the type services
316     		Map<String,PermissionTypeService> permissionTypeServices = getPermissionTypeServicesByTemplateId( permissions );
317     		// build a map of permissions by template ID
318     		Map<String, List<PermissionBo>> permissionMap = groupPermissionsByTemplate(permissions);
319     		// loop over the different templates, matching all of the same template against the type
320     		// service at once
321     		for ( String templateId : permissionMap.keySet() ) {
322     			PermissionTypeService permissionTypeService = permissionTypeServices.get( templateId );
323     			List<PermissionBo> permissionList = permissionMap.get(templateId);
324                 List<Permission> immutablePermissionList = new ArrayList<Permission>();
325                 for (PermissionBo bo : permissionList) {immutablePermissionList.add(PermissionBo.to(bo));}
326                 List<Permission> matchingPermissions = permissionTypeService.getMatchingPermissions(
327                         permissionDetails, immutablePermissionList );
328                 List<PermissionBo> matchingPermissionBos = new ArrayList<PermissionBo>();
329                 for (Permission perm : matchingPermissions) {matchingPermissionBos.add(PermissionBo.from(perm)); }
330 				applicablePermissions.addAll(matchingPermissionBos);
331 
332     		}
333     	}
334     	return applicablePermissions;
335     }
336 
337     /**
338      * @see org.kuali.rice.kim.service.PermissionService#getPermissionAssignees(String, String, Map<String, String>, Map<String, String>)
339      */
340     public List<PermissionAssigneeInfo> getPermissionAssignees( String namespaceCode, String permissionName, Map<String, String> permissionDetails, Map<String, String> qualification ) {
341     	List<PermissionAssigneeInfo> results = new ArrayList<PermissionAssigneeInfo>();
342     	List<String> roleIds = getRoleIdsForPermission( namespaceCode, permissionName, permissionDetails);
343     	if ( roleIds.isEmpty() ) {
344     		return results;
345     	}
346     	Collection<RoleMembership> roleMembers = getRoleService().getRoleMembers( roleIds,
347                 qualification );
348     	for ( RoleMembership rm : roleMembers ) {
349     		if ( rm.getMemberTypeCode().equals( Role.PRINCIPAL_MEMBER_TYPE ) ) {
350     			results.add( new PermissionAssigneeInfo( rm.getMemberId(), null, rm.getDelegates() ) );
351     		} else if ( rm.getMemberTypeCode().equals( Role.GROUP_MEMBER_TYPE ) ) {
352     			results.add( new PermissionAssigneeInfo( null, rm.getMemberId(), rm.getDelegates() ) );
353     		}
354     	}
355     	return results;
356     }
357     
358     public List<PermissionAssigneeInfo> getPermissionAssigneesForTemplateName( String namespaceCode, String permissionTemplateName, Map<String, String> permissionDetails, Map<String, String> qualification ) {
359     	List<PermissionAssigneeInfo> results = new ArrayList<PermissionAssigneeInfo>();
360     	List<String> roleIds = getRoleIdsForPermissionTemplate( namespaceCode, permissionTemplateName, permissionDetails);
361     	if ( roleIds.isEmpty() ) {
362     		return results;
363     	}
364     	Collection<RoleMembership> roleMembers = getRoleService().getRoleMembers( roleIds,
365                 qualification);
366     	for ( RoleMembership rm : roleMembers ) {
367     		if ( rm.getMemberTypeCode().equals( Role.PRINCIPAL_MEMBER_TYPE ) ) {
368     			results.add( new PermissionAssigneeInfo( rm.getMemberId(), null, rm.getDelegates() ) );
369     		} else { // a group membership
370     			results.add( new PermissionAssigneeInfo( null, rm.getMemberId(), rm.getDelegates() ) );
371     		}
372     	}
373     	return results;
374     }
375     
376     public boolean isPermissionAssigned( String namespaceCode, String permissionName, Map<String, String> permissionDetails ) {
377     	return !getRoleIdsForPermission(namespaceCode, permissionName, permissionDetails).isEmpty();
378     }
379     
380     public boolean isPermissionDefined( String namespaceCode, String permissionName, Map<String, String> permissionDetails ) {
381     	// get all the permission objects whose name match that requested
382     	PermissionBo permissions = getPermissionImplsByName( namespaceCode, permissionName );
383     	// now, filter the full list by the detail passed
384     	return !getMatchingPermissions( Collections.singletonList(permissions), permissionDetails ).isEmpty();
385     }
386     
387     public boolean isPermissionDefinedForTemplateName( String namespaceCode, String permissionTemplateName, Map<String, String> permissionDetails ) {
388     	// get all the permission objects whose name match that requested
389     	List<PermissionBo> permission = getPermissionImplsByTemplateName( namespaceCode, permissionTemplateName );
390     	// now, filter the full list by the detail passed
391         if (permission != null) {
392     	    return !getMatchingPermissions( permission, permissionDetails ).isEmpty();
393         }
394         return false;
395     }
396  
397     public List<String> getRoleIdsForPermission( String namespaceCode, String permissionName, Map<String, String> permissionDetails) {
398     	// get all the permission objects whose name match that requested
399     	PermissionBo permissions = getPermissionImplsByName( namespaceCode, permissionName );
400     	// now, filter the full list by the detail passed
401     	List<PermissionBo> applicablePermissions = getMatchingPermissions( Collections.singletonList( permissions ), permissionDetails );
402     	List<String> roleIds = getRolesForPermissionsFromCache( applicablePermissions );
403     	if ( roleIds == null ) {
404     		roleIds = permissionDao.getRoleIdsForPermissions( applicablePermissions );
405     		addRolesForPermissionsToCache( applicablePermissions, roleIds );
406     	}
407     	return roleIds;    	
408     }
409 
410     protected List<String> getRoleIdsForPermissionTemplate( String namespaceCode, String permissionTemplateName, Map<String, String> permissionDetails ) {
411     	// get all the permission objects whose name match that requested
412     	List<PermissionBo> permissions = getPermissionImplsByTemplateName( namespaceCode, permissionTemplateName );
413     	// now, filter the full list by the detail passed
414     	List<PermissionBo> applicablePermissions = getMatchingPermissions( permissions, permissionDetails );
415     	List<String> roleIds = getRolesForPermissionsFromCache( applicablePermissions );
416     	if ( roleIds == null ) {
417     		roleIds = permissionDao.getRoleIdsForPermissions( applicablePermissions );
418     		addRolesForPermissionsToCache( applicablePermissions, roleIds );
419     	}
420     	return roleIds;
421     }
422 
423     @Override
424     public List<String> getRoleIdsForPermissions( List<Permission> permissions ) {
425         List<PermissionBo> permBos = new ArrayList<PermissionBo>();
426         for (Permission perm : permissions) { permBos.add(PermissionBo.from(perm));}
427     	List<String> roleIds = getRolesForPermissionsFromCache( permBos );
428     	if ( roleIds == null ) {
429     		roleIds = permissionDao.getRoleIdsForPermissions( permBos );
430     		addRolesForPermissionsToCache( permBos, roleIds );
431     	}
432     	return roleIds;
433     }
434 
435     // --------------------
436     // Permission Data
437     // --------------------
438     
439     /**
440      * @see org.kuali.rice.kim.service.PermissionService#getPermission(java.lang.String)
441      */
442     public Permission getPermission(String permissionId) {
443     	PermissionBo impl = getPermissionImpl( permissionId );
444     	if ( impl != null ) {
445     		return PermissionBo.to(impl);
446     	}
447     	return null;
448     }
449     
450     /**
451      * @see org.kuali.rice.kim.service.PermissionService#getPermissionsByTemplateName(String, String)
452      */
453     public List<Permission> getPermissionsByTemplateName(String namespaceCode, String permissionTemplateName) {
454         List<PermissionBo> impls = getPermissionImplsByTemplateName( namespaceCode, permissionTemplateName );
455         List<Permission> permissions = new ArrayList<Permission>(impls.size());
456         for (PermissionBo impl : impls) {
457             permissions.add(PermissionBo.to(impl));
458         }
459     	return permissions;
460     }
461 
462 	/**
463      * @see org.kuali.rice.kim.service.PermissionService#getPermissionsByName(String, String)
464      */
465 
466     public Permission getPermissionsByName(String namespaceCode, String permissionName) {
467     	PermissionBo impls = getPermissionImplsByName( namespaceCode, permissionName );
468         return PermissionBo.to(impls);
469     }
470     
471     @SuppressWarnings("unchecked")
472 	protected PermissionBo getPermissionImpl(String permissionId) {
473     	if ( StringUtils.isBlank( permissionId ) ) {
474     		return null;
475     	}
476     	PermissionBo permissions  = getBusinessObjectService().findByPrimaryKey( PermissionBo.class, Collections.singletonMap(KimConstants.PrimaryKeyConstants.ID, permissionId) );
477 
478     	return permissions;
479     }
480     
481     @SuppressWarnings("unchecked")
482 	protected List<PermissionBo> getPermissionImplsByTemplateName( String namespaceCode, String permissionTemplateName ) {
483         HashMap<String,Object> pk = new HashMap<String,Object>( 3 );
484         pk.put( "template.namespaceCode", namespaceCode );
485         pk.put( "template.name", permissionTemplateName );
486         pk.put( KRADPropertyConstants.ACTIVE, "Y" );
487         return new ArrayList<PermissionBo>(getBusinessObjectService().findMatching( PermissionBo.class, pk ));
488     }
489 
490     @SuppressWarnings("unchecked")
491 	protected PermissionBo getPermissionImplsByName( String namespaceCode, String permissionName ) {
492         HashMap<String,Object> pk = new HashMap<String,Object>( 3 );
493         pk.put( KimConstants.UniqueKeyConstants.NAMESPACE_CODE, namespaceCode );
494         pk.put( KimConstants.UniqueKeyConstants.PERMISSION_NAME, permissionName );
495         pk.put( KRADPropertyConstants.ACTIVE, "Y" );
496         Collection<PermissionBo> c = getBusinessObjectService().findMatching( PermissionBo.class, pk );
497         return c != null && c.iterator().hasNext() ? c.iterator().next() : null;
498     }
499 
500     
501     
502     // --------------------
503     // Support Methods
504     // --------------------
505 	
506 	
507 	protected RoleService getRoleService() {
508 		if ( roleService == null ) {
509 			roleService = KimApiServiceLocator.getRoleService();
510 		}
511 
512 		return roleService;
513 	}
514 
515 	public void setRoleService(RoleService roleService) {
516 		this.roleService = roleService;
517 	}
518 
519 	public KimPermissionDao getPermissionDao() {
520 		return this.permissionDao;
521 	}
522 
523 	public void setPermissionDao(KimPermissionDao permissionDao) {
524 		this.permissionDao = permissionDao;
525 	}
526 
527 	@SuppressWarnings("unchecked")
528 	public List<Permission> lookupPermissions(Map<String, String> searchCriteria, boolean unbounded){
529 		Collection baseResults = null;
530 		Lookupable permissionLookupable = KNSServiceLocator.getLookupable(
531                 KRADServiceLocatorWeb.getBusinessObjectDictionaryService().getLookupableID(PermissionImpl.class));
532 		permissionLookupable.setBusinessObjectClass(PermissionImpl.class);
533 		if ( unbounded ) {
534 		    baseResults = permissionLookupable.getSearchResultsUnbounded( searchCriteria );
535 		} else {
536 			baseResults = permissionLookupable.getSearchResults(searchCriteria);
537 		}
538 		List<Permission> results = new ArrayList<Permission>( baseResults.size() );
539 		for ( PermissionBo resp : (Collection<PermissionBo>)baseResults ) {
540 			results.add( PermissionBo.to(resp) );
541 		}
542 		if ( baseResults instanceof CollectionIncomplete ) {
543 			results = new CollectionIncomplete<Permission>( results, ((CollectionIncomplete<KimPermissionInfo>)baseResults).getActualSizeIfTruncated() );
544 		}		
545 		return results;
546 	}
547 
548 	public String getPermissionDetailLabel( String permissionId, String kimTypeId, String attributeName) {
549     	// get the type service for this permission
550 		PermissionTypeService typeService = getPermissionTypeService(null, null, null, permissionId);
551 		if ( typeService != null ) {
552 			// ask the type service for the attribute definition for the given attribute name
553 			final KimAttributeField attributeDef = KimAttributeField.findAttribute(attributeName, typeService.getAttributeDefinitions( kimTypeId ));
554 			return attributeDef != null ? attributeDef.getAttributeField().getLongLabel() : "Missing Def: " + attributeName;
555 		} else {
556 			return "No Label: " + attributeName;
557 		}
558 	}
559 	
560 	/**
561 	 * @see org.kuali.rice.kim.service.PermissionService#getPermissionTemplate(java.lang.String)
562 	 */
563 	public KimPermissionTemplateInfo getPermissionTemplate(String permissionTemplateId) {
564 		KimPermissionTemplateImpl impl = getBusinessObjectService().findBySinglePrimaryKey( KimPermissionTemplateImpl.class, permissionTemplateId );
565 		if ( impl != null ) {
566 			return impl.toSimpleInfo();
567 		}
568 		return null;
569 	}
570 
571 	/**
572 	 * This overridden method ...
573 	 * 
574 	 * @see org.kuali.rice.kim.service.PermissionService#getPermissionTemplateByName(java.lang.String, java.lang.String)
575 	 */
576 	public KimPermissionTemplateInfo getPermissionTemplateByName(String namespaceCode,
577 			String permissionTemplateName) {
578 		Map<String,String> criteria = new HashMap<String,String>(2);
579 		criteria.put( KimConstants.UniqueKeyConstants.NAMESPACE_CODE, namespaceCode );
580 		criteria.put( KimConstants.UniqueKeyConstants.PERMISSION_TEMPLATE_NAME, permissionTemplateName );
581 		KimPermissionTemplateImpl impl = (KimPermissionTemplateImpl)getBusinessObjectService().findByPrimaryKey( KimPermissionTemplateImpl.class, criteria );
582 		if ( impl != null ) {
583 			return impl.toSimpleInfo();
584 		}
585 		return null;
586 	}
587 	
588 	@SuppressWarnings("unchecked")
589 	public List<KimPermissionTemplateInfo> getAllTemplates() {
590 		if ( allTemplates == null ) {
591 			Map<String,String> criteria = new HashMap<String,String>(1);
592 			criteria.put( KRADPropertyConstants.ACTIVE, "Y" );
593 			List<KimPermissionTemplateImpl> impls = (List<KimPermissionTemplateImpl>)getBusinessObjectService().findMatching( KimPermissionTemplateImpl.class, criteria );
594 			List<KimPermissionTemplateInfo> infos = new ArrayList<KimPermissionTemplateInfo>( impls.size() );
595 			for ( KimPermissionTemplateImpl impl : impls ) {
596 				infos.add( impl.toSimpleInfo() );
597 			}
598 			Collections.sort(infos, new Comparator<KimPermissionTemplateInfo>() {
599 				public int compare(KimPermissionTemplateInfo tmpl1,
600 						KimPermissionTemplateInfo tmpl2) {
601 					int result = 0;
602 					result = tmpl1.getNamespaceCode().compareTo(tmpl2.getNamespaceCode());
603 					if ( result != 0 ) {
604 						return result;
605 					}
606 					result = tmpl1.getName().compareTo(tmpl2.getName());
607 					return result;
608 				}
609 			});
610 			allTemplates = infos;
611 		}
612 		return allTemplates;
613 	}
614 
615     
616 	
617 	private DataDictionaryService dataDictionaryService;
618 	protected DataDictionaryService getDataDictionaryService() {
619 		if(dataDictionaryService == null){
620 			dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService();
621 		}
622 		return dataDictionaryService;
623 	}
624 	
625 
626     public List<String> getRoleIdsForPermissionId(String permissionId) {
627         Permission permissionInfo = getPermission(permissionId);
628 
629         List<PermissionBo> applicablePermissions = new ArrayList<PermissionBo>();
630         applicablePermissions.add(PermissionBo.from(permissionInfo));
631 
632         List<String> roleIds = getRolesForPermissionsFromCache(applicablePermissions);
633         if (roleIds == null) {
634             roleIds = permissionDao.getRoleIdsForPermissions(applicablePermissions);
635             addRolesForPermissionsToCache(applicablePermissions, roleIds);
636         }
637 
638         return roleIds;
639     }
640 
641     public Permission getPermissionsByNameIncludingInactive(String namespaceCode, String permissionName) {
642         PermissionBo impls = getPermissionImplsByNameIncludingInactive(namespaceCode, permissionName);
643         return PermissionBo.to(impls);
644     }
645 	
646     @SuppressWarnings("unchecked")
647     protected PermissionBo getPermissionImplsByNameIncludingInactive(String namespaceCode, String permissionName) {
648         HashMap<String, Object> pk = new HashMap<String, Object>(2);
649         pk.put(KimConstants.UniqueKeyConstants.NAMESPACE_CODE, namespaceCode);
650         pk.put(KimConstants.UniqueKeyConstants.PERMISSION_NAME, permissionName);
651         Collection<PermissionBo> c = getBusinessObjectService().findMatching( PermissionBo.class, pk );
652         return c != null && c.iterator().hasNext() ? c.iterator().next() : null;
653     }
654     
655     public int getRefreshPeriodInSeconds() {
656         try {
657             return (int)(new Integer(ConfigContext.getCurrentContextConfig().getProperty(KimConstants.CacheRefreshPeriodSeconds.KIM_CACHE_PERMISSION_REFRESH_PERIOD_SECONDS)));
658         } catch (NumberFormatException e) {
659     		// The cache will never expire when refreshPeriod is set to -1
660     		return -1;        		
661         }
662     }
663 }