/* groupInactivateWizard.java A wizard to facilitate the inactivation of a group. Created: 23 June 1998 Module By: Mike Mulvaney ----------------------------------------------------------------------- Ganymede Directory Management System Copyright (C) 1996-2014 The University of Texas at Austin Ganymede is a registered trademark of The University of Texas at Austin Contact information Author Email: ganymede_author@arlut.utexas.edu Email mailing list: ganymede@arlut.utexas.edu US Mail: Computer Science Division Applied Research Laboratories The University of Texas at Austin PO Box 8029, Austin TX 78713-8029 Telephone: (512) 835-3200 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package arlut.csd.ganymede.gasharl; import java.rmi.RemoteException; import java.util.Enumeration; import java.util.Hashtable; import java.util.HashMap; import java.util.Map; import java.util.Vector; import arlut.csd.ganymede.common.GanyPermissionsException; import arlut.csd.ganymede.common.Invid; import arlut.csd.ganymede.common.NotLoggedInException; import arlut.csd.ganymede.common.ObjectHandle; import arlut.csd.ganymede.common.QueryResult; import arlut.csd.ganymede.common.ReturnVal; import arlut.csd.ganymede.server.DBObject; import arlut.csd.ganymede.server.Ganymede; import arlut.csd.ganymede.server.GanymedeSession; import arlut.csd.ganymede.server.GanymediatorWizard; import arlut.csd.ganymede.server.InvidDBField; /*------------------------------------------------------------------------------ class groupInactivateWizard ------------------------------------------------------------------------------*/ /** * <p>This class handles the inactivation of a group. If any users have * this group as the home group, then those users will need a new * group designated as the home group. The dialog will prompt with a * choice list containing the groups that the user is a member of. If * the user doesn't have any other groups, the wizard will cancel the * inactivation and provide a list of the users who need new groups.</p> * * <p>If the group doesn't have any home users, then a simple * confirmation dialog will be presented.</p> * * States: * <table> * <tr><td>Start</td><td>Explanation. If group has no home users, then the dialog is just a confirmation, and next state is 50.</td></tr> * <tr><td>1</td><td>List of home users, along with choice of new group. If a user has no other groups, this will instead be a list of those users and a cancel message.</td></tr> * <tr><td>2</td><td>Confirmation of inactivation..</td></tr> * <tr><td>50</td><td>Confirmaion of inactivation.</td></tr> * </table> */ public class groupInactivateWizard extends GanymediatorWizard { private final static boolean debug = true; // --- /** * The user-level session context that this wizard is acting in. This * object is used to handle necessary checkpoint/rollback activity by * this wizard, as well as to handle any necessary label lookups. */ GanymedeSession session; /** * The actual group object that this wizard is acting on. */ groupCustom groupObject; /** * Hash of user names to user objects. This is used to keep track * of the open user objects, which will be passed to the * groupCustom. They will be passed in another hash, however. */ Map<String, DBObject> userObjectHash = new HashMap<String, DBObject>(); /** * Hash of group names to group object invid's. This is used to process * the string choices we get back if the user requested users' home * groups be changed. */ Hashtable groupNameHash = new Hashtable(); String ckp_label; /** * Vector field of all the home users for this group. If there are no * home users, getStartDialog chooses a different path for the dialog. */ InvidDBField homeField; // From superclass. // int state; /** * * This constructor registers the wizard as an active wizard * on the provided session. * * @param session The GanymedeSession object that this wizard will * use to interact with the Ganymede data store. * @param group The group object that this wizard will work with. * @param ckp_label The checkpoint label used to finish up the * inactivation * */ public groupInactivateWizard(GanymedeSession session, groupCustom group, String ckp_label) throws RemoteException { super(session); this.session = session; this.groupObject = group; this.ckp_label = ckp_label; } /** * * This method provides a default response if a user * hits cancel on a wizard dialog. This should be * subclassed if a wizard wants to provide a more * detailed cancel response. * */ public ReturnVal cancel() { return fail("Group Inactivation Canceled", "Group Inactivation Canceled", "OK", null, "ok.gif"); } /** * * This method starts off the wizard process * * If the home users field is empty, then we don't have to worry * about cleaning up any of the users. So we just ask the user if * they really want to inactivate, and set the state to 50 so the * next dialog will just be a confirmation if everything worked. * * Otherwise, follow the normal 1,2 state procession. */ public ReturnVal processDialog0() { homeField = groupObject.getInvidField(groupSchema.HOMEUSERS); StringBuffer buffer = new StringBuffer(); if (homeField.size() == 0) { if (debug) { System.err.println("groupInactivateWizard: there are no home users."); } buffer.append("Inactivating " + groupObject.getLabel()); buffer.append("\n\nAre you sure you want to inactivate " + groupObject.getLabel() + "?"); setNextState(50); return continueOn("Group Inactivate Dialog", buffer.toString(), "Inactivate", "Cancel", "question.gif"); } else { if (debug) { System.err.println("groupInactivateWizard: creating inactivation wizard, there are " + homeField.size() + " home users."); } buffer.append("Inactivating "); buffer.append(groupObject.getLabel()); buffer.append("\n\nThis group will be rendered unusable, but will be kept "); buffer.append("in the database for 3 months to preserve accounting information.\n\n"); buffer.append("If any users have this group as their home group, you will "); buffer.append("have to provide a new home group for them."); return continueOn("Group Inactivate Dialog", buffer.toString(), "Ok", "Cancel", "question.gif"); } } /** * * Process first result from the client.. if we get to this point, the * user said ok, go ahead.. we don't have any parameters to deal with * at this point. * */ public ReturnVal processDialog1() throws NotLoggedInException { ReturnVal retVal; retVal = continueOn("Group Inactivation Wizard", "Choose a new home group for each user. The choices " + "are the groups the user is currently a memeber of. " + "If the user isn't in any other groups, then I guess " + "I will give you something else.", "Ok", "Cancel", "question.gif"); // First get a list of the home users QueryResult qr = homeField.encodedValues(); Vector homeUsers = qr.getHandles(); if (debug) { System.err.println("groupInactivateWizard: " + homeUsers.size() + " home users."); } // Loop through the home users, and find out what other groups // they are in. What if they are in no groups? Must have a // button or something. Vector rejectedUsers = new Vector(); for (int i = 0; i < homeUsers.size(); i++) { ObjectHandle lh = (ObjectHandle) homeUsers.elementAt(i); DBObject user; if (debug) { System.err.println("groupInactivateWizard: dealing with user: " + lh.getLabel()); } ReturnVal rv = session.edit_db_object(lh.getInvid()); if ((rv != null) && (!rv.didSucceed())) { if (debug) { System.err.println("groupInactivateWizard: edit_db_object failed, aborting"); } groupObject.inactivate(false, true, ckp_label); // not sucessful, from wizard return rv; } user = (DBObject) rv.getObject(); // Keep a reference to the user object. userObjectHash.put(lh.getLabel(), user); InvidDBField userGroupField = user.getInvidField(userSchema.GROUPLIST); QueryResult queryr = userGroupField.encodedValues(); // The list of groups will contain the current group, // which is being inactivated. We need to remove that // group from the vector. Vector handles = queryr.getHandles(); Invid invid = groupObject.getInvid(); for (int j = 0; j < handles.size(); j++) { if (queryr.getInvid(j).equals(invid)) { handles.removeElementAt(j); break; } else { groupNameHash.put(queryr.getLabel(j), queryr.getInvid(j)); } } if (debug) { System.err.println("groupInactivateWizard: " + lh.getLabel() + " has " + handles.size() + " groups left, besides the home group."); } // If there aren't any groups left, get the hell out of // here. The user is not ready for this operation. if (handles.size() < 1) { rejectedUsers.addElement(lh.getLabel()); } retVal.getDialog().addChoice(lh.getLabel(), queryr.getLabels()); } // were there users who had no other groups to belong to? If so, // we'll need to refuse the group inactivation. if (rejectedUsers.size() != 0) { StringBuffer rejectedBuffer = new StringBuffer(); rejectedBuffer.append("The following users don't have any other groups:\n\n"); for (int i = 0; i < rejectedUsers.size(); i++) { rejectedBuffer.append(rejectedUsers.elementAt(i)); rejectedBuffer.append("\n"); } rejectedBuffer.append("\nYou must modify or inactivate these users before "); rejectedBuffer.append("inactivating this group."); groupObject.inactivate(false, true, ckp_label); // Not sucessful, from wizard return fail("Group Inactivate Failed", rejectedBuffer.toString(), "Ok", null, "ok.gif"); } if (debug) { System.err.println("groupInactivateWizard: returning dialog with all the choices, state now = 2"); } return retVal; } /** * If we are called here, the user responded to a dialog asking them * to select new home groups for users who had this group chosen as * their home group. * */ public ReturnVal processDialog2() throws NotLoggedInException { ReturnVal finalReturnVal = ReturnVal.success(); if (debug) { System.err.println("groupInactivateWizard: state = 2"); } Enumeration keys = getKeys(); while (keys.hasMoreElements()) { String userName = (String) keys.nextElement(); String newHomeGroupName = (String) getParam(userName); Invid newHomeGroup = (Invid) groupNameHash.get(newHomeGroupName); if (debug) { System.err.println("groupInactivateWizard: fixing up " + userName); } DBObject usr = userObjectHash.get(userName); if (debug) { System.err.println("Setting home group for " + userName + " to " + newHomeGroup); } InvidDBField ugField = usr.getInvidField(userSchema.HOMEGROUP); try { ReturnVal retv = ugField.setValue(newHomeGroup); if ((retv != null) && (! retv.didSucceed())) { groupObject.inactivate(false, true, ckp_label); return retv; } else { finalReturnVal.unionRescan(retv); } } catch (GanyPermissionsException ex) { return Ganymede.createErrorDialog(this.session, "permissions", "permissions error setting home group object " + ex); } } groupObject.inactivate(true, true, ckp_label); if (debug) { System.err.println("groupInactivateWizard: all done."); } ReturnVal result = success("Group Inactivation performed", "The Group has been inactivated, and all " + "the users have new home groups.", "OK", null, "ok.gif").unionRescan(finalReturnVal); System.err.println(result.dumpRescanInfo()); return result; } /** * This is the state where there are no home users, and the first * "are you sure?" dialog has been shown. From here, we just inactivate * the group and go about our merry ways. */ public ReturnVal processDialog50() throws NotLoggedInException { groupObject.inactivate(true, true, ckp_label); if (debug) { System.err.println("groupInactivateWizard: all done, no home groups."); } return success("Group Inactivation performed", "The group has been inactivated.", "OK", null, "ok.gif"); } }