View Javadoc

1   /**
2    * Copyright 2005-2014 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.lookup;
17  
18  import org.apache.commons.beanutils.PropertyUtils;
19  import org.apache.commons.lang.StringUtils;
20  import org.kuali.rice.core.api.membership.MemberType;
21  import org.kuali.rice.kim.api.KimConstants;
22  import org.kuali.rice.kim.api.role.RoleService;
23  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
24  import org.kuali.rice.kim.impl.permission.GenericPermissionBo;
25  import org.kuali.rice.kim.impl.permission.PermissionBo;
26  import org.kuali.rice.kim.impl.permission.UberPermissionBo;
27  import org.kuali.rice.kim.impl.role.RoleBo;
28  import org.kuali.rice.kim.impl.role.RolePermissionBo;
29  import org.kuali.rice.kns.lookup.HtmlData;
30  import org.kuali.rice.krad.bo.BusinessObject;
31  import org.kuali.rice.krad.lookup.CollectionIncomplete;
32  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
33  import org.kuali.rice.krad.service.LookupService;
34  import org.kuali.rice.krad.util.KRADConstants;
35  import org.kuali.rice.krad.util.UrlFactory;
36  
37  import java.lang.reflect.InvocationTargetException;
38  import java.util.ArrayList;
39  import java.util.HashMap;
40  import java.util.List;
41  import java.util.Map;
42  import java.util.Properties;
43  
44  public class PermissionLookupableHelperServiceImpl extends RoleMemberLookupableHelperServiceImpl {
45  
46  	private static final long serialVersionUID = -3578448525862270477L;
47  
48  	private transient LookupService lookupService;
49  	private transient RoleService roleService;
50  	private volatile String genericPermissionDocumentTypeName;
51  
52  	@Override
53  	public List<HtmlData> getCustomActionUrls(BusinessObject businessObject, List pkNames) {
54      	List<HtmlData> htmlDataList = new ArrayList<HtmlData>();
55      	// convert the PermissionBo class into an UberPermission object
56      	businessObject = new GenericPermissionBo((UberPermissionBo)businessObject);
57          if (allowsMaintenanceEditAction(businessObject)) {
58          	htmlDataList.add(getUrlData(businessObject, KRADConstants.MAINTENANCE_EDIT_METHOD_TO_CALL, pkNames));
59          }
60          if (allowsMaintenanceNewOrCopyAction()) {
61          	htmlDataList.add(getUrlData(businessObject, KRADConstants.MAINTENANCE_COPY_METHOD_TO_CALL, pkNames));
62          }
63          return htmlDataList;
64  	}
65  
66  	protected String getActionUrlHref(BusinessObject businessObject, String methodToCall, List pkNames){
67          Properties parameters = new Properties();
68          parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, methodToCall);
69          parameters.put(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, businessObject.getClass().getName());
70          parameters.put(KRADConstants.OVERRIDE_KEYS, KimConstants.PrimaryKeyConstants.PERMISSION_ID);
71          parameters.put(KRADConstants.COPY_KEYS, KimConstants.PrimaryKeyConstants.PERMISSION_ID);
72          if (StringUtils.isNotBlank(getReturnLocation())) {
73          	parameters.put(KRADConstants.RETURN_LOCATION_PARAMETER, getReturnLocation());
74  		}
75          parameters.putAll(getParametersFromPrimaryKey(businessObject, pkNames));
76          return UrlFactory.parameterizeUrl(KRADConstants.MAINTENANCE_ACTION, parameters);
77      }
78  	
79  	@Override
80  	protected String getMaintenanceDocumentTypeName() {
81  		//using DCL idiom to cache genericPermissionDocumentTypeName.
82          //see effective java 2nd ed. pg. 71
83          String g = genericPermissionDocumentTypeName;
84          if (g == null) {
85              synchronized (this) {
86                  g = genericPermissionDocumentTypeName;
87                  if (g == null) {
88                      genericPermissionDocumentTypeName = g = getMaintenanceDocumentDictionaryService().getDocumentTypeName(
89                              GenericPermissionBo.class);
90                  }
91              }
92          }
93  
94          return g;
95  	}
96  		
97  	@Override
98  	protected List<? extends BusinessObject> getMemberSearchResults(Map<String, String> searchCriteria, boolean unbounded) {
99  		Map<String, String> permissionSearchCriteria = buildSearchCriteria(searchCriteria);
100 		Map<String, String> roleSearchCriteria = buildRoleSearchCriteria(searchCriteria);
101 		boolean permissionCriteriaEmpty = permissionSearchCriteria==null || permissionSearchCriteria.isEmpty();
102 		boolean roleCriteriaEmpty = roleSearchCriteria==null || roleSearchCriteria.isEmpty();
103 		
104 		List<UberPermissionBo> permissionSearchResultsCopy = new CollectionIncomplete<UberPermissionBo>(new ArrayList<UberPermissionBo>(), new Long(0));
105 		if(!permissionCriteriaEmpty && !roleCriteriaEmpty){
106 			permissionSearchResultsCopy = getCombinedSearchResults(permissionSearchCriteria, roleSearchCriteria, unbounded);
107 		} else if(permissionCriteriaEmpty && !roleCriteriaEmpty){
108 			permissionSearchResultsCopy = getPermissionsWithRoleSearchCriteria(roleSearchCriteria, unbounded);
109 		} else if(!permissionCriteriaEmpty && roleCriteriaEmpty){
110 			permissionSearchResultsCopy = getPermissionsWithPermissionSearchCriteria(permissionSearchCriteria, unbounded);
111 		} else if(permissionCriteriaEmpty && roleCriteriaEmpty){
112 			return getAllPermissions(unbounded);
113 		}
114 		return permissionSearchResultsCopy;
115 	}
116 	
117 	private List<UberPermissionBo> getAllPermissions(boolean unbounded){
118 		List<UberPermissionBo> permissions = searchPermissions(new HashMap<String, String>(), unbounded);
119 		for(UberPermissionBo permission: permissions) {
120 			populateAssignedToRoles(permission);
121         }
122 		return permissions;
123 	}
124 	
125 	private List<UberPermissionBo> getCombinedSearchResults(
126 			Map<String, String> permissionSearchCriteria, Map<String, String> roleSearchCriteria, boolean unbounded){
127 		List<UberPermissionBo> permissionSearchResults = searchPermissions(permissionSearchCriteria, unbounded);
128 		List<RoleBo> roleSearchResults = searchRoles(roleSearchCriteria, unbounded);
129 		List<UberPermissionBo> permissionsForRoleSearchResults = getPermissionsForRoleSearchResults(roleSearchResults, unbounded);
130 		List<UberPermissionBo> matchedPermissions = new CollectionIncomplete<UberPermissionBo>(
131 			new ArrayList<UberPermissionBo>(), getActualSizeIfTruncated(permissionsForRoleSearchResults));
132 		if((permissionSearchResults!=null && !permissionSearchResults.isEmpty()) && 
133 				(permissionsForRoleSearchResults!=null && !permissionsForRoleSearchResults.isEmpty())){
134 			for(UberPermissionBo permission: permissionSearchResults){
135 				for(UberPermissionBo permissionFromRoleSearch: permissionsForRoleSearchResults){
136 					if(permissionFromRoleSearch.getId().equals(permission.getId())) {
137 						matchedPermissions.add(permissionFromRoleSearch);
138                     }
139 				}
140 			}
141 		}
142 		return matchedPermissions;
143 	}
144 	
145 	private List<UberPermissionBo> searchPermissions(Map<String, String> permissionSearchCriteria, boolean unbounded){
146 		return getPermissionsSearchResultsCopy(new ArrayList<PermissionBo>(getLookupService().findCollectionBySearchHelper(
147 				PermissionBo.class, permissionSearchCriteria, unbounded)));
148 
149 	}
150 	
151 	private List<UberPermissionBo> getPermissionsWithRoleSearchCriteria(Map<String, String> roleSearchCriteria, boolean unbounded){
152 		return getPermissionsForRoleSearchResults(searchRoles(roleSearchCriteria, unbounded), unbounded);
153 	}
154 
155 	private List<UberPermissionBo> getPermissionsForRoleSearchResults(List<RoleBo> roleSearchResults, boolean unbounded){
156 		Long actualSizeIfTruncated = getActualSizeIfTruncated(roleSearchResults);
157 		List<UberPermissionBo> permissions = new ArrayList<UberPermissionBo>();
158 		List<UberPermissionBo> tempPermissions;
159 		List<String> collectedPermissionIds = new ArrayList<String>();
160 		Map<String, String> permissionCriteria;
161 		
162 		for(RoleBo roleImpl: roleSearchResults){
163 			permissionCriteria = new HashMap<String, String>();
164 			permissionCriteria.put("rolePermissions.roleId", roleImpl.getId());
165 			tempPermissions = searchPermissions(permissionCriteria, unbounded);
166 			actualSizeIfTruncated += getActualSizeIfTruncated(tempPermissions);
167 			for(UberPermissionBo permission: tempPermissions){
168 				if(!collectedPermissionIds.contains(permission.getId())){
169 					populateAssignedToRoles(permission);
170 					collectedPermissionIds.add(permission.getId());
171 					permissions.add(permission);
172 				}
173 			}
174 			//need to find roles that current role is a member of and build search string
175 			List<String> parentRoleIds = KimApiServiceLocator.getRoleService().getMemberParentRoleIds(MemberType.ROLE.getCode(), roleImpl.getId());
176 			for (String parentRoleId : parentRoleIds) {
177 				Map<String, String> roleSearchCriteria = new HashMap<String, String>();
178 				roleSearchCriteria.put("roleId", parentRoleId);
179 				//get all parent role permissions and merge them with current permissions
180 				permissions = mergePermissionLists(permissions, getPermissionsWithRoleSearchCriteria(roleSearchCriteria, unbounded));
181 			}
182 		}
183 		
184 		return new CollectionIncomplete<UberPermissionBo>(permissions, actualSizeIfTruncated);
185 	}
186 	
187 
188 	private void populateAssignedToRoles(UberPermissionBo permission){
189 		Map<String, String> criteria;
190 		for(RolePermissionBo rolePermission: permission.getRolePermissions()){
191 			if ( rolePermission.isActive() ) {
192 				criteria = new HashMap<String, String>();
193 				criteria.put("id", rolePermission.getRoleId());
194 	//			permission.getAssignedToRoles().add((RoleBo)getBusinessObjectService().findByPrimaryKey(RoleBo.class, criteria));
195                 RoleBo roleBo = getBusinessObjectService().findByPrimaryKey(RoleBo.class, criteria);
196                 permission.getAssignedToRoles().add(roleBo);
197 
198 			}
199 		}
200 	}
201 
202 	private List<UberPermissionBo> getPermissionsWithPermissionSearchCriteria(
203 			Map<String, String> permissionSearchCriteria, boolean unbounded){
204 		String detailCriteriaStr = permissionSearchCriteria.remove( DETAIL_CRITERIA );
205 		Map<String, String> detailCriteria = parseDetailCriteria(detailCriteriaStr);
206 
207 		final List<UberPermissionBo> permissions = searchPermissions(permissionSearchCriteria, unbounded);
208 		List<UberPermissionBo> filteredPermissions = new CollectionIncomplete<UberPermissionBo>(
209 				new ArrayList<UberPermissionBo>(), getActualSizeIfTruncated(permissions));
210 		for(UberPermissionBo perm: permissions){
211 			if ( detailCriteria.isEmpty() ) {
212 				filteredPermissions.add(perm);
213 				populateAssignedToRoles(perm);
214 			} else {
215 				if ( isMapSubset( new HashMap<String, String>(perm.getDetails()), detailCriteria ) ) {
216 					filteredPermissions.add(perm);
217 					populateAssignedToRoles(perm);
218 				}
219 			}
220 		}
221 		return filteredPermissions;
222 	}
223 	
224 	private List<UberPermissionBo> getPermissionsSearchResultsCopy(List<PermissionBo> permissionSearchResults){
225 		List<UberPermissionBo> permissionSearchResultsCopy = new CollectionIncomplete<UberPermissionBo>(
226 				new ArrayList<UberPermissionBo>(), getActualSizeIfTruncated(permissionSearchResults));
227 		for(PermissionBo permissionBo: permissionSearchResults){
228 			UberPermissionBo permissionCopy = new UberPermissionBo();
229 
230             try {
231                 PropertyUtils.copyProperties(permissionCopy, permissionBo);
232                 //Hack for tomcat 7 KULRICE-5927
233                 permissionCopy.setTemplate(permissionBo.getTemplate());
234             } catch (IllegalAccessException e) {
235                 throw new RuntimeException("unable to copy properties");
236             } catch (InvocationTargetException e) {
237                 throw new RuntimeException("unable to copy properties");
238             } catch (NoSuchMethodException e) {
239                 throw new RuntimeException("unable to copy properties");
240             }
241 
242             permissionSearchResultsCopy.add(permissionCopy);
243 		}
244 		return permissionSearchResultsCopy;
245 	}
246 
247 	/**
248 	 * @return the lookupService
249 	 */
250 	public synchronized LookupService getLookupService() {
251 		if ( lookupService == null ) {
252 			lookupService = KRADServiceLocatorWeb.getLookupService();
253 		}
254 		return lookupService;
255 	}
256 
257 	public synchronized RoleService getRoleService() {
258 		if (roleService == null) {
259 			roleService = KimApiServiceLocator.getRoleService();
260 		}
261 		return roleService;
262 	}
263 
264 	private List<UberPermissionBo> mergePermissionLists(List<UberPermissionBo> perm1, List<UberPermissionBo> perm2) {
265 		List<UberPermissionBo> returnList = new ArrayList<UberPermissionBo>(perm1);
266 		List<String> permissionIds = new ArrayList<String>(perm1.size());
267 		for (UberPermissionBo perm : returnList) {
268 			permissionIds.add(perm.getId());
269 		}
270 		for (int i=0; i<perm2.size(); i++) {
271 		    if (!permissionIds.contains(perm2.get(i).getId())) {
272 		    	returnList.add(perm2.get(i));
273 		    }
274 		}
275 		return returnList;
276 	}
277 }