001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/providers/tags/sakai_2-4-1/cm/cm-authz-provider/src/java/org/sakaiproject/coursemanagement/impl/provider/CourseManagementGroupProvider.java $
003: * $Id: CourseManagementGroupProvider.java 20456 2007-01-19 00:58:21Z jholtzman@berkeley.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.coursemanagement.impl.provider;
021:
022: import java.util.HashMap;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Map;
026:
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029: import org.sakaiproject.coursemanagement.api.CourseManagementService;
030: import org.sakaiproject.coursemanagement.api.Section;
031: import org.sakaiproject.authz.api.GroupProvider;
032:
033: /**
034: * A Sakai GroupProvider that utilizes the CourseManagementService and the
035: * CmMappingService to supply authz data to Sakai. This implementation uses
036: * a list of RoleResolvers, which can be used to resolve a user's role in a section
037: * based on memberships in parent objects such as CourseSets.
038: *
039: * @author <a href="mailto:jholtzman@berkeley.edu">Josh Holtzman</a>
040: */
041: public class CourseManagementGroupProvider implements GroupProvider {
042: private static final Log log = LogFactory
043: .getLog(CourseManagementGroupProvider.class);
044:
045: /** The course management service */
046: CourseManagementService cmService;
047:
048: /** The role resolvers to use when looking for CM roles in the hierarchy*/
049: List<RoleResolver> roleResolvers;
050:
051: /** The ordered list of role preferences. Roles earlier in the list are preferred to those later in the list. */
052: List<String> rolePreferences;
053:
054: // GroupProvider methods
055:
056: /**
057: * This method is not longer in use in Sakai. It should be removed from the
058: * GroupProvider interface.
059: */
060: public String getRole(String id, String user) {
061: log
062: .error("\n------------------------------------------------------------------\n");
063: log
064: .error("THIS METHOD IS NEVER CALLED IN SAKAI. WHAT HAPPENED???");
065: log
066: .error("\n------------------------------------------------------------------\n");
067: return null;
068: }
069:
070: /**
071: * Provides a Map of a user ids to (Sakai) roles for a given AuthzGroup. Since a
072: * user may be both enrolled in a mapped EnrollmentSet and have a Membership
073: * role in a mapped Section, the following order of precedence is applied:
074: * Official Instructor, Enrollment, membership
075: */
076: public Map getUserRolesForGroup(String id) {
077: if (log.isDebugEnabled())
078: log.debug("------------------CMGP.getUserRolesForGroup("
079: + id + ")");
080: Map<String, String> userRoleMap = new HashMap<String, String>();
081:
082: String[] sectionEids = unpackId(id);
083: if (log.isDebugEnabled())
084: log.debug(id + " is mapped to " + sectionEids.length
085: + " sections");
086:
087: for (Iterator<RoleResolver> rrIter = roleResolvers.iterator(); rrIter
088: .hasNext();) {
089: RoleResolver rr = rrIter.next();
090:
091: for (int i = 0; i < sectionEids.length; i++) {
092: String sectionEid = sectionEids[i];
093: Section section = cmService.getSection(sectionEid);
094: if (log.isDebugEnabled())
095: log.debug("Looking for roles in section "
096: + sectionEid);
097:
098: Map<String, String> rrUserRoleMap = rr.getUserRoles(
099: cmService, section);
100: // Only add the roles if the user isn't already in the map. Earlier resolvers take precedence.
101: for (Iterator<String> rrRoleIter = rrUserRoleMap
102: .keySet().iterator(); rrRoleIter.hasNext();) {
103: String userEid = rrRoleIter.next();
104: String existingRole = userRoleMap.get(userEid);
105: String rrRole = rrUserRoleMap.get(userEid);
106:
107: // The Role Resolver has found no role for this user
108: if (rrRole == null) {
109: continue;
110: }
111:
112: // Add or replace the role in the map if this is a more preferred role than the previous role
113: if (existingRole == null) {
114: if (log.isDebugEnabled())
115: log.debug("Adding " + userEid
116: + " to userRoleMap with role="
117: + rrRole);
118: userRoleMap.put(userEid, rrRole);
119: } else if (preferredRole(existingRole, rrRole)
120: .equals(rrRole)) {
121: if (log.isDebugEnabled())
122: log.debug("Changing " + userEid
123: + "'s role in userRoleMap from "
124: + existingRole + " to " + rrRole
125: + " for section " + sectionEid);
126: userRoleMap.put(userEid, rrRole);
127: }
128: }
129: }
130: }
131: if (log.isDebugEnabled())
132: log.debug("_____________getUserRolesForGroup="
133: + userRoleMap);
134: return userRoleMap;
135: }
136:
137: /**
138: * Provides a map of AuthzGroup ids to Sakai roles for a given user. Enrollment
139: * is overridden by a membership role.
140: */
141: public Map getGroupRolesForUser(String userEid) {
142: if (log.isDebugEnabled())
143: log.debug("------------------CMGP.getGroupRolesForUser("
144: + userEid + ")");
145: Map<String, String> groupRoleMap = new HashMap<String, String>();
146:
147: for (Iterator rrIter = roleResolvers.iterator(); rrIter
148: .hasNext();) {
149: RoleResolver rr = (RoleResolver) rrIter.next();
150: Map<String, String> rrGroupRoleMap = rr.getGroupRoles(
151: cmService, userEid);
152: if (log.isDebugEnabled())
153: log.debug("Found " + rrGroupRoleMap.size()
154: + " groups for " + userEid + " from resolver "
155: + rr.getClass().getName());
156:
157: // Only add the section eids if they aren't already in the map (earlier resolvers take precedence) or if the new role has a higher preference.
158: for (Iterator<String> rrRoleIter = rrGroupRoleMap.keySet()
159: .iterator(); rrRoleIter.hasNext();) {
160: String sectionEid = rrRoleIter.next();
161: String existingRole = groupRoleMap.get(sectionEid);
162: String rrRole = rrGroupRoleMap.get(sectionEid);
163:
164: // The Role Resolver has found no role for this section
165: if (rrRole == null) {
166: continue;
167: }
168:
169: if (existingRole == null) {
170: if (log.isDebugEnabled())
171: log.debug("Adding " + sectionEid
172: + " to groupRoleMap with sakai role"
173: + rrRole + " for user " + userEid);
174: groupRoleMap.put(sectionEid, rrRole);
175: } else if (preferredRole(existingRole, rrRole).equals(
176: rrRole)) {
177: if (log.isDebugEnabled())
178: log.debug("Changing " + userEid
179: + "'s role in groupRoleMap from "
180: + existingRole + " to " + rrRole
181: + " for section " + sectionEid);
182: groupRoleMap.put(userEid, rrRole);
183: }
184: }
185: }
186: if (log.isDebugEnabled())
187: log.debug("______________getGroupRolesForUser="
188: + groupRoleMap);
189: return groupRoleMap;
190: }
191:
192: /**
193: * {@inheritDoc}
194: */
195: public String packId(String[] ids) {
196: if (ids == null || ids.length == 0) {
197: return null;
198: }
199:
200: if (ids.length == 1) {
201: return ids[0];
202: }
203:
204: StringBuffer sb = new StringBuffer();
205: for (int i = 0; i < ids.length; i++) {
206: sb.append(ids[i]);
207: if (i < ids.length - 1) {
208: sb.append("+");
209: }
210: }
211: return sb.toString();
212: }
213:
214: public String[] unpackId(String id) {
215: if (id == null) {
216: return new String[0];
217: }
218: return id.split("\\+");
219: }
220:
221: // Utility methods
222:
223: public void init() {
224: if (log.isInfoEnabled())
225: log.info("initializing " + this .getClass().getName());
226: }
227:
228: public void destroy() {
229: if (log.isInfoEnabled())
230: log.info("destroying " + this .getClass().getName());
231: }
232:
233: // Dependency injection
234:
235: public void setCmService(CourseManagementService cmService) {
236: this .cmService = cmService;
237: }
238:
239: public void setRoleResolvers(List<RoleResolver> roleResolvers) {
240: this .roleResolvers = roleResolvers;
241: }
242:
243: public String preferredRole(String one, String other) {
244: int oneIndex = rolePreferences.indexOf(one);
245: int otherIndex = rolePreferences.indexOf(other);
246: if (otherIndex == -1) {
247: return one;
248: }
249: if (oneIndex == -1) {
250: return other;
251: }
252: return oneIndex < otherIndex ? one : other;
253: }
254:
255: public void setRolePreferences(List<String> rolePreferences) {
256: this.rolePreferences = rolePreferences;
257: }
258: }
|