001: /* Copyright 2001 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.channels.groupsmanager;
007:
008: import java.util.Calendar;
009: import java.util.Enumeration;
010: import java.util.Iterator;
011:
012: import org.jasig.portal.ChannelStaticData;
013: import org.jasig.portal.IChannel;
014: import org.jasig.portal.IServant;
015: import org.jasig.portal.PortalException;
016: import org.jasig.portal.channels.groupsmanager.permissions.GroupsManagerAdminPermissions;
017: import org.jasig.portal.channels.groupsmanager.permissions.GroupsManagerBlockEntitySelectPermissions;
018: import org.jasig.portal.channels.groupsmanager.permissions.GroupsManagerDefaultPermissions;
019: import org.jasig.portal.groups.IEntityGroup;
020: import org.jasig.portal.groups.IGroupMember;
021: import org.jasig.portal.groups.ILockableEntityGroup;
022: import org.jasig.portal.services.GroupService;
023: import org.w3c.dom.Document;
024: import org.w3c.dom.Element;
025:
026: /**
027: * A Factory that produces a Groups Manager <code>IServant</code> for
028: * one of several groups-management related tasks. Each specific servant
029: * is available from one of the methods documented below.
030: *
031: * Groups Manager servants can relieve uPortal channels from having to
032: * implement complicated custom GUIs for managing group memberships or
033: * selecting groups and entities.
034: *
035: * @see org.jasig.portal.channels.CChannelManager
036: * as an example of using Groups Manager servants
037: *
038: * @author Alex Vigdor
039: * @version $Revision: 36398 $
040: */
041:
042: public class CGroupsManagerServantFactory implements
043: GroupsManagerConstants {
044: private static CGroupsManagerServantFactory _instance;
045: private static int UID = 0;
046:
047: /** Creates new CGroupsManagerServantFactory */
048: protected CGroupsManagerServantFactory() {
049: }
050:
051: protected static CGroupsManagerServant getGroupsServant() {
052: return new CGroupsManagerServant();
053: }
054:
055: /**
056: * Returns a servant that is used to select IGroupMembers. The
057: * list of selected IGroupMembers is available via the getResults() method
058: *
059: * @return IServant
060: * @param staticData
061: * the master channel's staticData
062: * @param message
063: * a custom message to present the user to explain what they should select
064: * @throws PortalException
065: */
066: public static IServant getGroupsServantforSelection(
067: ChannelStaticData staticData, String message)
068: throws PortalException {
069: return getGroupsServantforSelection(staticData, message, null);
070: }
071:
072: /**
073: * Returns a servant that is used to select IGroupMembers. The
074: * list of selected IGroupMembers is available via the getResults() method
075: *
076: * @return IServant
077: * @param staticData
078: * the master channel's staticData
079: * @param message
080: * a custom message to present the user to explain what they should select
081: * @param type
082: * the distinguished group name representing the desired root group for
083: * selection, e.g. GroupService.EVERYONE or GroupService.ALL_CATEGORIES
084: * @param allowFinish
085: * whether or not the user can "finish" selecting. if false, the servant
086: * method "isFinished()" will always return false; the master must have
087: * some other mechanism for allowing the user to change screens.
088: * @param allowEntitySelect
089: * if false, only groups can be selected
090: * @param members
091: * an IGroupMember[] of pre-selected members.
092: * @throws PortalException
093: */
094: public static IServant getGroupsServantforSelection(
095: ChannelStaticData staticData, String message, String type,
096: boolean allowFinish, boolean allowEntitySelect,
097: IGroupMember[] members) throws PortalException {
098: return getGroupsServantforSelection(staticData, message, type,
099: allowFinish, allowEntitySelect, members, null);
100: }
101:
102: /**
103: * Returns a servant that is used to select IEntityGroups that the supplied
104: * GroupMember belongs to. Existing memberships are reflected as pre-
105: * selected groups.
106: *
107: * @return IServant
108: * @param staticData
109: * the master channel's staticData
110: * @param message
111: * a custom message to present the user to explain what they should select
112: * @param member
113: * The IGroupMember whose parent groups are to be selected
114: * @param allowFinish
115: * whether or not the user can "finish" selecting. if false, the servant
116: * method "isFinished()" will always return false; the master must have
117: * some other mechanism for allowing the user to change screens.
118: * @throws PortalException
119: */
120: public static IServant getGroupsServantforGroupMemberships(
121: ChannelStaticData staticData, String message,
122: IGroupMember member, boolean allowFinish)
123: throws PortalException {
124: CGroupsManagerServant servant = null;
125: String typeKey = null;
126:
127: try {
128: typeKey = GroupService.getRootGroup(member.getType())
129: .getKey();
130: } catch (Exception e) {
131: ;
132: }
133:
134: try {
135: servant = getGroupsServant();
136: ChannelStaticData slaveSD = cloneStaticData(staticData);
137: servant.setStaticData(slaveSD);
138: if (typeKey != null) {
139: servant.getSessionData().rootViewGroupID = Utility
140: .translateKeytoID(typeKey, servant
141: .getSessionData().getUnrestrictedData());
142: }
143: servant.getSessionData().highlightedGroupID = servant
144: .getSessionData().rootViewGroupID;
145: servant.getSessionData().mode = "select";
146: servant.getSessionData().allowFinish = allowFinish;
147: //servant.getSessionData().gmPermissions = GroupsManagerBlockEntitySelectPermissions.getInstance();
148: servant.getSessionData().gmPermissions = new GroupsManagerBlockEntitySelectPermissions(
149: getPermissionsPolicy(staticData));
150: //servant.getSessionData().blockEntitySelect = true;
151: if (message != null) {
152: servant.getSessionData().customMessage = message;
153: }
154: CGroupsManagerUnrestrictedSessionData ursd = servant
155: .getSessionData().getUnrestrictedData();
156: Document viewDoc = servant.getSessionData().model;
157: Element rootElem = viewDoc.getDocumentElement();
158: try {
159: Iterator parents = member.getContainingGroups();
160: IEntityGroup parent;
161: while (parents.hasNext()) {
162: parent = (IEntityGroup) parents.next();
163: Element parentElem = GroupsManagerXML
164: .getGroupMemberXml(parent, false, null,
165: ursd);
166: parentElem.setAttribute("selected", "true");
167: rootElem.appendChild(parentElem);
168: }
169: } catch (Exception e) {
170: Utility.logMessage("ERROR", e.toString(), e);
171: }
172: } catch (Exception e) {
173: throw (new PortalException(
174: "CGroupsManagerServantFactory - unable to initialize servant"));
175: }
176: return (IServant) servant;
177: }
178:
179: /**
180: * Returns a servant that is used to select IGroupMembers. The
181: * list of selected IGroupMembers is available via the getResults() method
182: *
183: * @return IServant
184: * @param staticData
185: * the master channel's staticData
186: * @param message
187: * a custom message to present the user to explain what they should select
188: * @param type
189: * the distinguished group name representing the desired root group for
190: * selection, e.g. GroupService.EVERYONE or GroupService.ALL_CATEGORIES
191: * @throws PortalException
192: */
193: public static IServant getGroupsServantforSelection(
194: ChannelStaticData staticData, String message, String type)
195: throws PortalException {
196: return getGroupsServantforSelection(staticData, message, type,
197: true, true);
198: }
199:
200: /**
201: * Returns a servant that is used to select IGroupMembers. The
202: * list of selected IGroupMembers is available via the getResults() method
203: *
204: * @return IServant
205: * @param staticData
206: * the master channel's staticData
207: * @param message
208: * a custom message to present the user to explain what they should select
209: * @param type
210: * the distinguished group name representing the desired root group for
211: * selection, e.g. GroupService.EVERYONE or GroupService.ALL_CATEGORIES
212: * @param allowFinish
213: * whether or not the user can "finish" selecting. if false, the servant
214: * method "isFinished()" will always return false; the master must have
215: * some other mechanism for allowing the user to change screens.
216: * @param allowEntitySelect
217: * if false, only groups can be selected
218: * @throws PortalException
219: */
220: public static IServant getGroupsServantforSelection(
221: ChannelStaticData staticData, String message, String type,
222: boolean allowFinish, boolean allowEntitySelect)
223: throws PortalException {
224: return getGroupsServantforSelection(staticData, message, type,
225: allowFinish, allowEntitySelect, new IGroupMember[0]);
226: }
227:
228: /**
229: * Returns a servant with the group corresponding to the provided key selected
230: * and locked for editing. Only add/remove member functions are enabled -
231: * group name, description and permissions are not editable.
232: *
233: * @return IServant
234: * @param staticData
235: * @param groupKey
236: * the group to be managed
237: * @throws PortalException
238: */
239: public static IServant getGroupsServantforAddRemove(
240: ChannelStaticData staticData, String groupKey)
241: throws PortalException {
242: long time1 = Calendar.getInstance().getTime().getTime();
243: CGroupsManagerServant servant;
244: try {
245: ILockableEntityGroup lockedGroup = GroupService
246: .findLockableGroup(groupKey, staticData
247: .getAuthorizationPrincipal()
248: .getPrincipalString());
249: lockedGroup.getClass();
250: servant = getGroupsServant();
251: ChannelStaticData slaveSD = cloneStaticData(staticData);
252:
253: ((IChannel) servant).setStaticData(slaveSD);
254: servant.getSessionData().mode = MEMBERS_ONLY_MODE;
255: servant.getSessionData().lockedGroup = lockedGroup;
256: servant.getSessionData().highlightedGroupID = Utility
257: .translateKeytoID(groupKey, servant
258: .getSessionData().getUnrestrictedData());
259: servant.getSessionData().defaultRootViewGroupID = Utility
260: .translateKeytoID(groupKey, servant
261: .getSessionData().getUnrestrictedData());
262: } catch (Exception e) {
263: Utility.logMessage("ERROR", e.toString(), e);
264: throw (new PortalException(
265: "CGroupsManagerServantFactory - unable to initialize servant"));
266: }
267: long time2 = Calendar.getInstance().getTime().getTime();
268: Utility.logMessage("INFO", "CGroupsManagerFactory took "
269: + String.valueOf((time2 - time1))
270: + " ms to instantiate add/remove servant");
271: return (IServant) servant;
272: }
273:
274: protected static ChannelStaticData cloneStaticData(
275: ChannelStaticData sd) {
276: ChannelStaticData rsd = (ChannelStaticData) sd.clone();
277: Enumeration srd = rsd.keys();
278: while (srd.hasMoreElements()) {
279: rsd.remove(srd.nextElement());
280: }
281: return rsd;
282: }
283:
284: protected static synchronized CGroupsManagerServantFactory instance() {
285: if (_instance == null) {
286: _instance = new CGroupsManagerServantFactory();
287: }
288: return _instance;
289: }
290:
291: /**
292: * Returns the next sequential identifier which is used to uniquely
293: * identify an element. This identifier is held in the Element "id" attribute.
294: * "0" is reserved for the Group containing the Initial Contexts for the user.
295: * @return String
296: */
297: public static synchronized String getNextUid() {
298: // max size of int = (2 to the 32 minus 1) = 2147483647
299: Utility.logMessage("DEBUG",
300: "GroupsManagerXML::getNextUid(): Start");
301: if (UID > 2147483600) {
302: // the value 0 is reserved for the group holding the initial group contexts
303: UID = 0;
304: }
305: String newUid = Calendar.getInstance().getTime().getTime()
306: + "grpsservant" + ++UID;
307: return newUid;
308: }
309:
310: /**
311: * Returns a servant that is used to select IGroupMembers. The
312: * list of selected IGroupMembers is available via the getResults() method
313: *
314: * @return IServant
315: * @param staticData
316: * the master channel's staticData
317: * @param message
318: * a custom message to present the user to explain what they should select
319: * @param type
320: * the distinguished group name representing the desired root group for
321: * selection, e.g. GroupService.EVERYONE or GroupService.ALL_CATEGORIES
322: * @param allowFinish
323: * whether or not the user can "finish" selecting. if false, the servant
324: * method "isFinished()" will always return false; the master must have
325: * some other mechanism for allowing the user to change screens.
326: * @param allowEntitySelect
327: * if false, only groups can be selected
328: * @param members
329: * an IGroupMember[] of pre-selected members.
330: * @param permissions
331: * an instance of IGroupsManagerPermissions
332: * @throws PortalException
333: */
334: public static IServant getGroupsServantforSelection(
335: ChannelStaticData staticData, String message, String type,
336: boolean allowFinish, boolean allowEntitySelect,
337: IGroupMember[] members,
338: IGroupsManagerPermissions permissions)
339: throws PortalException {
340: long time1 = System.currentTimeMillis();
341: CGroupsManagerServant servant;
342:
343: try {
344: servant = getGroupsServant();
345: ChannelStaticData slaveSD = cloneStaticData(staticData);
346: Utility
347: .logMessage(
348: "DEBUG",
349: "CGroupsManagerFactory::getGroupsServantforSelection: slaveSD before setting servant static data: "
350: + slaveSD);
351: servant.setStaticData(slaveSD);
352:
353: servant.getSessionData().mode = "select";
354: servant.getSessionData().allowFinish = allowFinish;
355:
356: // An instance of permissions and allowEntitySelect set to false both trigger the setting
357: // of the gmPermissions in sessionData. The permissions object takes precedence. If
358: // gmPermissions is not set here, the default policy will be set in GroupsManagerXML.
359: if (permissions != null) {
360: servant.getSessionData().gmPermissions = permissions;
361: } else if (!allowEntitySelect) {
362: servant.getSessionData().gmPermissions = new GroupsManagerBlockEntitySelectPermissions(
363: getPermissionsPolicy(staticData));
364: }
365:
366: if (message != null) {
367: servant.getSessionData().customMessage = message;
368: }
369: String typeKey = null;
370: if (type != null && !type.equals("")) {
371: try {
372: typeKey = GroupService.getDistinguishedGroup(type)
373: .getKey();
374: } catch (Exception e) {
375: ;
376: }
377: }
378: if (typeKey != null) {
379: servant.getSessionData().rootViewGroupID = Utility
380: .translateKeytoID(typeKey, servant
381: .getSessionData().getUnrestrictedData());
382: }
383: servant.getSessionData().highlightedGroupID = servant
384: .getSessionData().rootViewGroupID;
385: if (members != null && members.length > 0) {
386: Document viewDoc = servant.getSessionData().model;
387: CGroupsManagerUnrestrictedSessionData ursd = servant
388: .getSessionData().getUnrestrictedData();
389:
390: Element rootElem = viewDoc.getDocumentElement();
391: try {
392: for (int mm = 0; mm < members.length; mm++) {
393: IGroupMember mem = members[mm];
394: Element memelem = GroupsManagerXML
395: .getGroupMemberXml(mem, false, null,
396: ursd);
397: memelem.setAttribute("selected", "true");
398: rootElem.appendChild(memelem);
399: }
400: } catch (Exception e) {
401: Utility.logMessage("ERROR", e.toString(), e);
402: }
403: }
404: } catch (Exception e) {
405: Utility.logMessage("ERROR", e.toString(), e);
406: throw (new PortalException(
407: "CGroupsManagerServantFactory - unable to initialize servant"));
408: }
409: long time2 = System.currentTimeMillis();
410: Utility.logMessage("INFO", "CGroupsManagerFactory took "
411: + String.valueOf((time2 - time1))
412: + " ms to instantiate selection servant");
413: return (IServant) servant;
414: }
415:
416: /**
417: * Returns a permissions policy based upon the users role.
418: *
419: * @return IGroupsManagerPermissions
420: * @param staticData the master channel's staticData
421: * @throws PortalException
422: */
423: public static IGroupsManagerPermissions getPermissionsPolicy(
424: ChannelStaticData staticData) throws PortalException {
425: IGroupsManagerPermissions pp = null;
426: IEntityGroup admin = GroupService
427: .getDistinguishedGroup(GroupService.PORTAL_ADMINISTRATORS);
428: IGroupMember currUser = org.jasig.portal.services.AuthorizationService
429: .instance().getGroupMember(
430: staticData.getAuthorizationPrincipal());
431: boolean isAdminUser = (admin.deepContains(currUser));
432: if (isAdminUser)
433: pp = GroupsManagerAdminPermissions.getInstance();
434: else
435: pp = GroupsManagerDefaultPermissions.getInstance();
436: return pp;
437: }
438: }
|