/*
* RHQ Management Platform
* Copyright (C) 2005-2008 Red Hat, Inc.
* All rights reserved.
*
* 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 version 2 of the License.
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.enterprise.gui.legacy.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.Globals;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.rhq.enterprise.gui.legacy.AttrConstants;
import org.rhq.enterprise.gui.legacy.WebUser;
import org.rhq.enterprise.gui.legacy.beans.ReturnPath;
public class SessionUtils {
private static final Log log = LogFactory.getLog(SessionUtils.class);
// Limit the size of the return stack so that it
// doesn't grow to infinite proportions.
private static final int RETURN_STACK_MAX_SIZE = 128;
/**
* Retrieve the cached <code>WebUser</code> representing the user.
*
* @param session the http session
* @return null if the session or its attribute 'webUser' is invalid, the user otherwise
*/
public static WebUser getWebUser(HttpSession session) {
if (session == null) {
return null;
}
Object attr = session.getAttribute(AttrConstants.WEBUSER_SES_ATTR);
if (attr == null) {
return null;
}
WebUser user = (WebUser) attr;
log.debug("Loading WebUser");
/*
Subject subject = user.getSubject();
Integer sessionId = subject.getSessionId();
subject = LookupUtil.getSubjectManager().loadUserConfiguration(subject.getId());
subject.setSessionId(sessionId); // put the transient data back into our new subject
user = new WebUser(subject); // reset
*/
return user;
}
public static void setWebUser(HttpSession session, WebUser user) {
if (user == null) {
session.removeAttribute(AttrConstants.WEBUSER_SES_ATTR);
} else {
session.setAttribute(AttrConstants.WEBUSER_SES_ATTR, user);
}
}
/**
* Retrieve the array of pending ids stored under the named session attribute.
*
* @param session the http session
* @param attr the name of the session attribute
*/
public static Integer[] getList(HttpSession session, String attr) {
Object list = session.getAttribute(attr);
Integer[] pendingIds = null;
try {
pendingIds = (Integer[]) list;
} catch (ClassCastException e) {
List pendingIdsList = (List) list;
pendingIds = (Integer[]) pendingIdsList.toArray(new Integer[pendingIdsList.size()]);
}
if (pendingIds == null) {
pendingIds = new Integer[0];
}
return pendingIds;
}
/**
* Retrieve the <code>List</code> of pending ids stored under the named session attribute.
*
* @param session the http session
* @param attr the name of the session attribute
*/
public static List getListAsList(HttpSession session, String attr) {
Object list = session.getAttribute(attr);
List pendingIds = null;
try {
pendingIds = (List) list;
} catch (ClassCastException e) {
Integer[] pendingIdsArray = (Integer[]) list;
pendingIds = Arrays.asList(pendingIdsArray);
}
if (pendingIds == null) {
pendingIds = new ArrayList();
}
return pendingIds;
}
/**
* Retrieve the <code>List</code> of pending ids stored under the named session attribute.
*
* @param session the http session
* @param attr the name of the session attribute
*/
@SuppressWarnings("unchecked")
public static List<String> getListAsListStr(HttpSession session, String attr) {
Object list = session.getAttribute(attr);
List<String> pendingIds = null;
try {
pendingIds = (List<String>) list;
} catch (ClassCastException e) {
String[] pendingIdsArray = (String[]) list;
pendingIds = Arrays.asList(pendingIdsArray);
}
if (pendingIds == null) {
pendingIds = new ArrayList<String>();
}
return pendingIds;
}
/**
* Merge the given ids into the array of pending ids stored under the named session attribute.
*
* @param session the http session
* @param attr the name of the session attribute
* @param ids the ids to be added
*/
public static void addToList(HttpSession session, String attr, List ids) {
/* copy the selected pending ids over to the available
* ids. those that were copied will not be included in the final list of available users generated by theform
* prepare action. */
List pendingIds = (List) session.getAttribute(attr);
if (pendingIds == null) {
pendingIds = new ArrayList();
}
session.setAttribute(attr, mergeIds(pendingIds, ids));
}
public static void addToList(HttpSession session, String attr, Integer[] ids) {
addToList(session, attr, Arrays.asList(ids));
}
/**
* Merge the given ids into the array of pending ids stored under the named session attribute.
*
* @param session the http session
* @param attr the name of the session attribute
* @param ids the ids to be added
*/
public static void addToListStr(HttpSession session, String attr, List ids) {
/* copy the selected pending ids over to the available
* ids. those that were copied will not be included in the final list of available users generated by theform
* prepare action. */
List pendingIds = (List) session.getAttribute(attr);
if (pendingIds == null) {
pendingIds = new ArrayList();
}
session.setAttribute(attr, mergeStrIds(pendingIds, ids));
}
public static void addToList(HttpSession session, String attr, String[] ids) {
addToListStr(session, attr, Arrays.asList(ids));
}
/**
* Remove the given ids from the array of pending ids stored under the named session attribute.
*
* @param session the http session
* @param attr the name of the session attribute
* @param ids the ids to be removed
*/
public static void removeFromList(HttpSession session, String attr, List ids) {
/* remove the selected pending ids from the current list
*of pending ids. */
List pendingIds = (List) session.getAttribute(attr);
if (pendingIds == null) {
pendingIds = new ArrayList();
}
session.setAttribute(attr, grepIds(pendingIds, ids));
}
public static void removeFromList(HttpSession session, String attr, Integer[] ids) {
removeFromList(session, attr, Arrays.asList(ids));
}
/**
* Remove the given ids from the array of pending ids stored under the named session attribute.
*
* @param session the http session
* @param attr the name of the session attribute
* @param ids the ids to be removed
*/
public static void removeFromListStr(HttpSession session, String attr, List ids) {
/* remove the selected pending ids from the current list
*of pending ids. */
List pendingIds = (List) session.getAttribute(attr);
if (pendingIds == null) {
pendingIds = new ArrayList();
}
session.setAttribute(attr, grepStrIds(pendingIds, ids));
}
public static void removeFromList(HttpSession session, String attr, String[] ids) {
removeFromListStr(session, attr, Arrays.asList(ids));
}
/**
* Remove the array of pending ids stored under the named session attribute.
*
* @param session the http session
* @param attr the name of the session attribute
*/
public static void removeList(HttpSession session, String attr) {
session.removeAttribute(attr);
}
/**
* Retrieve the "return path" that locates the point at which a subflow was included into a primary workflow.
*
* @param session the http session
*/
public static String getReturnPath(HttpSession session) {
LinkedList stack = (LinkedList) session.getAttribute(AttrConstants.RETURN_LOC_SES_ATTR);
if ((stack == null) || stack.isEmpty()) {
return null;
}
ReturnPath returnPath = (ReturnPath) stack.getFirst();
return returnPath.getPath();
}
/**
* Set the "returnPath", the possible point of origin for a workflow.
*
* @param session the http session
* @param path the return path
*/
public static void setReturnPath(HttpSession session, String path) {
setReturnPath(session, path, Boolean.FALSE);
}
/**
* Set the "returnPath," the possible point of origin for a worklow
*
* @param session The http session.
* @param path The return path url represented as a String.
* @param ignore
*/
public static void setReturnPath(HttpSession session, String path, Boolean ignore) {
LinkedList stack = (LinkedList) session.getAttribute(AttrConstants.RETURN_LOC_SES_ATTR);
ReturnPath returnPath = new ReturnPath();
if (stack == null) {
stack = new LinkedList();
}
returnPath.setPath(path);
returnPath.setIgnore(ignore);
stack.addFirst(returnPath);
// don't let it grow too large.
if (stack.size() > RETURN_STACK_MAX_SIZE) {
stack.removeLast();
}
session.setAttribute(AttrConstants.RETURN_LOC_SES_ATTR, stack);
}
/**
* clear out the return path stack.
*/
public static void resetReturnPath(HttpSession session) {
LinkedList stack = new LinkedList();
session.setAttribute(AttrConstants.RETURN_LOC_SES_ATTR, stack);
}
/**
* Unset the "return path" that locates the point at which a subflow was included into a primary workflow.
*
* @param session the http session
*/
public static void unsetReturnPath(HttpSession session) {
LinkedList retstack = (LinkedList) session.getAttribute(AttrConstants.RETURN_LOC_SES_ATTR);
if ((retstack != null) && (retstack.size() >= 1)) {
retstack.removeFirst();
}
}
/**
* Retrieve wether the "return path" should be paid attention to for new. should default to false, which means that
* it is not ignored.
*
* @param session the http session
*
* @return whether or not to ignore the return path
*/
public static Boolean getReturnPathIgnoredForOk(HttpSession session) {
LinkedList stack = (LinkedList) session.getAttribute(AttrConstants.RETURN_LOC_SES_ATTR);
if ((stack == null) || stack.isEmpty()) {
return Boolean.FALSE;
}
ReturnPath returnPath = (ReturnPath) stack.getFirst();
if (returnPath == null) {
return Boolean.FALSE;
}
return returnPath.getIgnore();
}
/**
* Unset the "return path" that locates the point at which a subflow was included into a primary workflow.
*
* @param session the http session
*/
public static void unsetReturnPathIgnoredForOk(HttpSession session) {
LinkedList stack = (LinkedList) session.getAttribute(AttrConstants.RETURN_LOC_SES_ATTR);
ReturnPath returnPath = (ReturnPath) stack.getFirst();
returnPath.setIgnore(Boolean.TRUE);
}
/**
* Remove any old workflows
*
* @param session
* @param workflowName
*/
public static void clearWorkflow(HttpSession session, String workflowName) {
HashMap workflows = (HashMap) session.getAttribute(AttrConstants.WORKFLOW_SES_ATTR);
if (workflows != null) {
workflows.remove(workflowName);
}
}
/**
* Takes the current returnPath and pushes it onto the workflow's stack.
*
* @param session The HttpSesion to get and save the workflow to/from
* @param mapping Use the input attribute from this mapping if a returnPath is not defined in the current
* session.
* @param workflowName The name of the workflow scope to save the input under.
*/
public static void pushWorkflow(HttpSession session, ActionMapping mapping, String workflowName) {
HashMap workflows = (HashMap) session.getAttribute(AttrConstants.WORKFLOW_SES_ATTR);
if (workflows == null) {
workflows = new HashMap();
}
String returnPath = getReturnPath(session);
if (returnPath == null) {
returnPath = mapping.getInput();
}
LinkedList urlStack = (LinkedList) workflows.get(workflowName);
// whacking getIsFirst.. for some reason, even if i set the
// property to false in struts-config.xml, it's still getting
// set back to true. i can't have this, so i'm whacking the
// check altogether. doesn't seem to harm anything. -bcm 7/9/03
// if (urlStack == null || mapping.getIsFirst().booleanValue()) {
if (urlStack == null) {
urlStack = new LinkedList();
}
urlStack.addLast(returnPath);
workflows.put(workflowName, urlStack);
session.setAttribute(AttrConstants.WORKFLOW_SES_ATTR, workflows);
}
/**
* Takes the current returnPath and pops it off of the workflow's stack.
*
* @param session The HttpSesion to get and save the workflow to/from
* @param workflowName The name of the workflow scope to save the input under.
* @return return path or null if it can't be retrieved
*/
public static String popWorkflow(HttpSession session, String workflowName) {
HashMap workflows = (HashMap) session.getAttribute(AttrConstants.WORKFLOW_SES_ATTR);
if (workflows == null) {
return null;
}
LinkedList urlStack = (LinkedList) workflows.get(workflowName);
if ((urlStack == null) || urlStack.isEmpty()) {
return null;
}
String returnUrl = (String) urlStack.removeLast();
workflows.put(workflowName, urlStack);
session.setAttribute(AttrConstants.WORKFLOW_SES_ATTR, workflows);
return returnUrl;
}
/**
* Returns the size of a workflow's stack.
*
* @param session The HttpSesion to get and save the workflow to/from
* @param workflowName The name of the workflow scope to save the input under.
*/
public static int countWorkflow(HttpSession session, String workflowName) {
HashMap workflows = (HashMap) session.getAttribute(AttrConstants.WORKFLOW_SES_ATTR);
if (workflows == null) {
return 0;
}
LinkedList urlStack = (LinkedList) workflows.get(workflowName);
if ((urlStack == null) || urlStack.isEmpty()) {
return 0;
}
return urlStack.size();
}
private static List grepIds(List all, List matches) {
if ((all == null) || (matches == null)) {
return new ArrayList();
}
// build an index of matches
HashSet index = new HashSet();
Iterator mi = matches.iterator();
while (mi.hasNext()) {
index.add(mi.next());
}
// find everything that's not a match
ArrayList ids = new ArrayList();
Iterator ai = all.iterator();
while (ai.hasNext()) {
Integer id = (Integer) ai.next();
if (!index.contains(id)) {
ids.add(id);
}
}
return ids;
}
/**
* searches for strings which does not match
*/
private static List grepStrIds(List pending, List newItems) {
if ((pending == null) || (newItems == null)) {
return new ArrayList();
}
// build an index of matches
HashSet index = new HashSet();
Iterator mi = newItems.iterator();
while (mi.hasNext()) {
index.add(mi.next());
}
// find everything that's not a match
ArrayList ids = new ArrayList();
Iterator ai = pending.iterator();
while (ai.hasNext()) {
String id = (String) ai.next();
if (!index.contains(id)) {
ids.add(id);
}
}
return ids;
}
private static List mergeIds(List orig, List added) {
if ((orig == null) && (added == null)) {
return new ArrayList();
}
if (orig == null) {
return added;
}
if (added == null) {
return orig;
}
// build an index of orig and add originals
ArrayList ids = new ArrayList();
HashSet index = new HashSet();
Iterator oi = orig.iterator();
while (oi.hasNext()) {
Object next = oi.next();
index.add(next);
ids.add(next);
}
// add anything that's not in the index
Iterator ai = added.iterator();
while (ai.hasNext()) {
Integer id = (Integer) ai.next();
if (!index.contains(id)) {
ids.add(id);
}
}
return ids;
}
/**
* same as the mergeIds except using strings IDs of form: .
*/
private static List mergeStrIds(List orig, List added) {
if ((orig == null) && (added == null)) {
return new ArrayList();
}
if (orig == null) {
return added;
}
if (added == null) {
return orig;
}
// build an index of orig and add originals
ArrayList ids = new ArrayList();
HashSet index = new HashSet();
Iterator oi = orig.iterator();
while (oi.hasNext()) {
Object next = oi.next();
index.add(next);
ids.add(next);
}
// add anything that's not in the index
Iterator ai = added.iterator();
while (ai.hasNext()) {
String id = (String) ai.next();
if (!index.contains(id)) {
ids.add(id);
}
}
return ids;
}
/**
* Set a confirmation message upon completion of a user action.
*
* @param session The servlet session object
* @param key the message resource key
*/
public static void setConfirmation(HttpSession session, String key) {
ActionMessage msg = new ActionMessage(key);
ActionMessages msgs = new ActionMessages();
msgs.add(ActionMessages.GLOBAL_MESSAGE, msg);
if (session != null) {
session.setAttribute(Globals.MESSAGE_KEY, msgs);
}
}
/**
* Set a confirmation message with a replacement value upon completion of a user action.
*
* @param session The servlet session object
* @param key the message resource key
* @param value0 the replacement value
*/
public static void setConfirmation(HttpSession session, String key, Object value0) {
ActionMessage msg = new ActionMessage(key, value0);
ActionMessages msgs = new ActionMessages();
msgs.add(ActionMessages.GLOBAL_MESSAGE, msg);
if (session != null) {
session.setAttribute(Globals.MESSAGE_KEY, msgs);
}
}
public static void unsetConfirmation(HttpSession session, String key) {
session.removeAttribute(Globals.MESSAGE_KEY);
}
/**
* Set an error message when a user action fails with a user-level error.
*
* @param session The servlet session object
* @param key the message resource key
*/
public static void setError(HttpSession session, String key) {
setError(session, key, ActionMessages.GLOBAL_MESSAGE);
}
/**
* Set an error message when a user action fails with a user-level error.
*
* @param session The servlet session object
* @param key the message resource key
* @param property the form property for which the error occurred
*/
public static void setError(HttpSession session, String key, String property) {
ActionMessage err = new ActionMessage(key);
ActionErrors errs = new ActionErrors();
errs.add(property, err);
if (session != null) {
session.setAttribute(Globals.ERROR_KEY, errs);
}
}
/**
* Set an error message with a replacement value when a user action fails with a user-level error.
*
* @param session The servlet session object
* @param key the message resource key
* @param value0 the replacement value
*/
public static void setError(HttpSession session, String key, Object value0) {
setError(session, key, value0, ActionMessages.GLOBAL_MESSAGE);
}
/**
* Set an error message with a replacement value when a user action fails with a user-level error.
*
* @param session The servlet session object
* @param key the message resource key
* @param value0 the replacement value
* @param property the form property for which the error occurred
*/
public static void setError(HttpSession session, String key, Object value0, String property) {
ActionMessage err = new ActionMessage(key, value0);
ActionMessages errs = new ActionErrors();
errs.add(property, err);
if (session != null) {
session.setAttribute(Globals.ERROR_KEY, errs);
}
}
public static void unsetError(HttpSession session) {
if (session != null) {
session.removeAttribute(Globals.ERROR_KEY);
}
}
/**
* Move the attribute from the session to request scope.
*
* @param request The request to move the attribute to.
* @param key Key indicating the attribute to move scope.
*/
public static void moveAttribute(HttpServletRequest request, String key) {
HttpSession session = request.getSession(false /* dont' create new one */);
if (session != null) {
request.setAttribute(key, session.getAttribute(key));
session.removeAttribute(key);
}
}
}