modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsFormPrepareAction.java | 111 ++++ modules/enterprise/gui/portal-war/src/main/webapp/admin/role/AddLdapRoleGroups.jsp | 2 modules/enterprise/gui/portal-war/src/main/webapp/admin/role/RoleLdapGroupsForm.jsp | 263 ++++++++++ modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManager.java | 2 4 files changed, 372 insertions(+), 6 deletions(-)
New commits: commit bdbc5d990cd959005e9a7355fc1ba5c1296187d7 Author: Simeon Pinder spinder@redhat.com Date: Tue Apr 27 12:49:48 2010 -0400
BZ 584994:i)pagination fix ii)added ldapgroupform iii)cache ldap group list
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsFormPrepareAction.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsFormPrepareAction.java index bd38c20..39fe62e 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsFormPrepareAction.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsFormPrepareAction.java @@ -19,11 +19,14 @@ package org.rhq.enterprise.gui.admin.role;
import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.NavigableSet; import java.util.Properties; import java.util.Set; +import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -43,6 +46,7 @@ import org.rhq.core.domain.authz.Role; import org.rhq.core.domain.resource.group.LdapGroup; import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList; +import org.rhq.core.domain.util.PageOrdering; import org.rhq.enterprise.gui.legacy.Constants; import org.rhq.enterprise.gui.legacy.util.RequestUtils; import org.rhq.enterprise.gui.legacy.util.SessionUtils; @@ -59,6 +63,8 @@ import org.rhq.enterprise.server.util.LookupUtil; * An Action that retrieves data to facilitate display of the form for adding groups to a role. */ public class AddLdapGroupsFormPrepareAction extends TilesAction { + final String LDAP_GROUP_CACHE = "ldapGroupCache"; + public ActionForward execute(ComponentContext context, ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { Log log = LogFactory.getLog(AddLdapGroupsFormPrepareAction.class.getName()); @@ -76,6 +82,9 @@ public class AddLdapGroupsFormPrepareAction extends TilesAction { RequestUtils.setError(request, Constants.ERR_ROLE_NOT_FOUND); return null; } + //use cached LDAP group list to avoid hitting ldap server each time ui pref changed. + Set<Map<String, String>> cachedAvailableLdapGroups = null; + cachedAvailableLdapGroups = (Set<Map<String, String>>) request.getSession().getAttribute(LDAP_GROUP_CACHE);
addForm.setR(role.getId());
@@ -93,21 +102,31 @@ public class AddLdapGroupsFormPrepareAction extends TilesAction { PageList<Map<String, String>> pendingGroups = new PageList<Map<String, String>>(pendingSet, 0, pcp); PageList<Map<String, String>> availableGroups = new PageList<Map<String, String>>(availableGroupsSet, 0, pca); /* pending groups are those on the right side of the "add - * to list" widget- awaiting association with the rolewhen the form's "ok" button is clicked. */ + * to list" widget- awaiting association with the role when the form's "ok" button is clicked. */ pendingGroupIds = SessionUtils.getListAsListStr(request.getSession(), Constants.PENDING_RESGRPS_SES_ATTR);
log.trace("getting pending groups for role [" + roleId + ")"); String name = "foo";
try { //defend against ldap communication runtime difficulties. - allGroups = LdapGroupManager.getInstance().findAvailableGroups(); - RoleManagerLocal roleManager = LookupUtil.getRoleManager();
+ if (cachedAvailableLdapGroups == null) { + allGroups = LdapGroupManager.getInstance().findAvailableGroups(); + } else {//reuse cached. + allGroups = cachedAvailableLdapGroups; + } + //store unmodified list in session. + cachedAvailableLdapGroups = allGroups; + + RoleManagerLocal roleManager = LookupUtil.getRoleManager(); + //retrieve currently assigned groups assignedList = roleManager.findLdapGroupsByRole(role.getId(), PageControl.getUnlimitedInstance());
+ //trim already defined from all groups returned. allGroups = filterExisting(assignedList, allGroups); Set<String> pendingIds = new HashSet<String>(pendingGroupIds);
+ //retrieve pending information pendingSet = findPendingGroups(pendingIds, allGroups); pendingGroups = new PageList<Map<String, String>>(pendingSet, pendingSet.size(), pcp);
@@ -118,6 +137,86 @@ public class AddLdapGroupsFormPrepareAction extends TilesAction {
availableGroupsSet = findAvailableGroups(pendingIds, allGroups); availableGroups = new PageList<Map<String, String>>(availableGroupsSet, availableGroupsSet.size(), pca); + + //We cannot reuse the PageControl mechanism as there are no database calls to retrieve list + // must replicate paging using existing web params, formula etc. + + //determine count to return up to 15|30|45 and page index + int returnAmount = pca.getPageSize(); + int returnIndex = pca.getPageNumber(); + + //determine sort order + PageOrdering sortOrder = pca.getPrimarySortOrder(); + if (sortOrder == null) { + sortOrder = PageOrdering.ASC; + pca.setPrimarySortOrder(sortOrder);//reset on pc + } + + //determine which column to sort on + String sortColumn = pca.getPrimarySortColumn(); + if (sortColumn == null) { + sortColumn = "lg.name"; + pca.setPrimarySort(sortColumn, sortOrder);//reset on pc + } + + //now sort based off these values and populate sizedAvailableGroups accordingly + ArrayList<Map<String, String>> groupsValues = availableGroups.getValues(); + + //store maps based off the keys and sort() + Map<Integer, Map> groupLookup = new HashMap<Integer, Map>(); + TreeMap<String, Integer> groupNames = new TreeMap<String, Integer>(); + TreeMap<String, Integer> groupDescriptions = new TreeMap<String, Integer>(); + for (int i = 0; i < groupsValues.size(); i++) { + Map<String, String> entry = groupsValues.get(i); + Integer key = Integer.valueOf(i); + groupLookup.put(key, entry); + groupNames.put(entry.get("name"), key); + groupDescriptions.put(entry.get("description"), key); + } + + //do calculations to determine how many sorted values to return. + int start, end; + start = (int) (returnIndex * returnAmount); + end = start + returnAmount; + PageList<Map<String, String>> sizedAvailableGroups = new PageList<Map<String, String>>(); + + //detect sort order + boolean descending = false; + if (sortOrder.DESC == sortOrder) { + descending = true; + } + //use sort column to determine which list to use + if (sortColumn.equalsIgnoreCase("lg.name")) { + int i = 0; + NavigableSet<String> keyList = groupNames.navigableKeySet(); + if (descending) { + keyList = groupNames.descendingKeySet(); + } + for (String key : keyList) { + if ((i >= start) && (i < end)) { + sizedAvailableGroups.add(groupLookup.get(groupNames.get(key))); + } + i++; + } + } else { + int i = 0; + NavigableSet<String> keyList = groupDescriptions.navigableKeySet(); + if (descending) { + keyList = groupNames.descendingKeySet(); + } + for (String key : keyList) { + if ((i >= start) && (i < end)) { + sizedAvailableGroups.add(groupLookup.get(groupDescriptions.get(key))); + } + i++; + } + } + //make sizedAvailableGroup the new reference to return. + availableGroups = sizedAvailableGroups; + //populate pagination elements for loaded elements. + availableGroups.setTotalSize(groupLookup.size()); + availableGroups.setPageControl(pca); + } catch (LdapFilterException lce) { ActionMessages actionMessages = new ActionMessages(); actionMessages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("admin.role.LdapGroupFilterMessage")); @@ -136,7 +235,9 @@ public class AddLdapGroupsFormPrepareAction extends TilesAction { request.setAttribute(Constants.PENDING_RESGRPS_ATTR, pendingGroups); request.setAttribute(Constants.NUM_PENDING_RESGRPS_ATTR, new Integer(pendingGroups.getTotalSize())); request.setAttribute(Constants.AVAIL_RESGRPS_ATTR, availableGroups); - request.setAttribute(Constants.NUM_AVAIL_RESGRPS_ATTR, new Integer(availableGroups.getTotalSize())); + request.setAttribute(Constants.NUM_AVAIL_RESGRPS_ATTR, new Integer(allGroups.size())); + //store cachedAvailableGroups in session so trim down ldap communication chatter. + request.getSession().setAttribute(LDAP_GROUP_CACHE, cachedAvailableLdapGroups);
return null; } @@ -175,4 +276,4 @@ public class AddLdapGroupsFormPrepareAction extends TilesAction { } return ret; } -} \ No newline at end of file +} diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/admin/role/AddLdapRoleGroups.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/admin/role/AddLdapRoleGroups.jsp index 93ec22e..4341a5e 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/admin/role/AddLdapRoleGroups.jsp +++ b/modules/enterprise/gui/portal-war/src/main/webapp/admin/role/AddLdapRoleGroups.jsp @@ -13,7 +13,7 @@
<tiles:insert definition=".portlet.error"/>
-<tiles:insert page="/admin/role/RoleGroupsForm.jsp"> +<tiles:insert page="/admin/role/RoleLdapGroupsForm.jsp"> <tiles:put name="availableResGrps" beanName="AvailableResGrps"/> <tiles:put name="numAvailableResGrps" beanName="NumAvailableResGrps"/> <tiles:put name="pendingResGrps" beanName="PendingResGrps"/> diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/admin/role/RoleLdapGroupsForm.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/admin/role/RoleLdapGroupsForm.jsp new file mode 100644 index 0000000..2880f22 --- /dev/null +++ b/modules/enterprise/gui/portal-war/src/main/webapp/admin/role/RoleLdapGroupsForm.jsp @@ -0,0 +1,263 @@ +<%@ page language="java" %> +<%@ page errorPage="/common/Error.jsp" %> +<%@ taglib uri="http://jakarta.apache.org/struts/tags-html-el" prefix="html" %> +<%@ taglib uri="http://jakarta.apache.org/struts/tags-tiles" prefix="tiles" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="/WEB-INF/tld/display.tld" prefix="display" %> + +<tiles:importAttribute name="availableResGrps"/> +<tiles:importAttribute name="numAvailableResGrps"/> +<tiles:importAttribute name="pendingResGrps"/> +<tiles:importAttribute name="numPendingResGrps"/> + +<script language="JavaScript" src="<html:rewrite page="/js/addRemoveWidget.js"/>" type="text/javascript"></script> +<c:set var="widgetInstanceName" value="addGroups"/> + +<script type="text/javascript"> +var pageData = new Array(); +initializeWidgetProperties('<c:out value="${widgetInstanceName}"/>'); +widgetProperties = getWidgetProperties('<c:out value="${widgetInstanceName}"/>'); +</script> + +<c:url var="selfPnaAction" value="/admin/role/RoleAdmin.do"> + <c:param name="mode" value="addLdapGroups"/> + <c:param name="r" value="${Role.id}"/> + <c:if test="${not empty param.psa}"> + <c:param name="psa" value="${param.psa}"/> + </c:if> + <c:if test="${not empty param.soa}"> + <c:param name="soa" value="${param.soa}"/> + </c:if> + <c:if test="${not empty param.sca}"> + <c:param name="sca" value="${param.sca}"/> + </c:if> + <c:if test="${not empty param.psp}"> + <c:param name="psp" value="${param.psp}"/> + </c:if> + <c:if test="${not empty param.pnp}"> + <c:param name="pnp" value="${param.pnp}"/> + </c:if> + <c:if test="${not empty param.sop}"> + <c:param name="sop" value="${param.sop}"/> + </c:if> + <c:if test="${not empty param.scp}"> + <c:param name="scp" value="${param.scp}"/> + </c:if> +</c:url> + +<c:url var="selfPnpAction" value="/admin/role/RoleAdmin.do"> + <c:param name="mode" value="addLdapGroups"/> + <c:param name="r" value="${Role.id}"/> + <c:if test="${not empty param.psa}"> + <c:param name="psa" value="${param.psa}"/> + </c:if> + <c:if test="${not empty param.pna}"> + <c:param name="pna" value="${param.pna}"/> + </c:if> + <c:if test="${not empty param.soa}"> + <c:param name="soa" value="${param.soa}"/> + </c:if> + <c:if test="${not empty param.sca}"> + <c:param name="sca" value="${param.sca}"/> + </c:if> + <c:if test="${not empty param.psp}"> + <c:param name="psp" value="${param.psp}"/> + </c:if> + <c:if test="${not empty param.sop}"> + <c:param name="sop" value="${param.sop}"/> + </c:if> + <c:if test="${not empty param.scp}"> + <c:param name="scp" value="${param.scp}"/> + </c:if> +</c:url> + +<c:url var="selfPsaAction" value="/admin/role/RoleAdmin.do"> + <c:param name="mode" value="addLdapGroups"/> + <c:param name="r" value="${Role.id}"/> + <c:if test="${not empty param.pna}"> + <c:param name="pna" value="${param.pna}"/> + </c:if> + <c:if test="${not empty param.soa}"> + <c:param name="soa" value="${param.soa}"/> + </c:if> + <c:if test="${not empty param.sca}"> + <c:param name="sca" value="${param.sca}"/> + </c:if> + <c:if test="${not empty param.pnp}"> + <c:param name="pnp" value="${param.pnp}"/> + </c:if> + <c:if test="${not empty param.psp}"> + <c:param name="psp" value="${param.psp}"/> + </c:if> + <c:if test="${not empty param.sop}"> + <c:param name="sop" value="${param.sop}"/> + </c:if> + <c:if test="${not empty param.scp}"> + <c:param name="scp" value="${param.scp}"/> + </c:if> +</c:url> + + +<c:url var="selfPspAction" value="/admin/role/RoleAdmin.do"> + <c:param name="mode" value="addLdapGroups"/> + <c:param name="r" value="${Role.id}"/> + <c:if test="${not empty param.pna}"> + <c:param name="pna" value="${param.pna}"/> + </c:if> + <c:if test="${not empty param.psa}"> + <c:param name="psa" value="${param.psa}"/> + </c:if> + <c:if test="${not empty param.soa}"> + <c:param name="soa" value="${param.soa}"/> + </c:if> + <c:if test="${not empty param.sca}"> + <c:param name="sca" value="${param.sca}"/> + </c:if> + <c:if test="${not empty param.pnp}"> + <c:param name="pnp" value="${param.pnp}"/> + </c:if> + <c:if test="${not empty param.sop}"> + <c:param name="sop" value="${param.sop}"/> + </c:if> + <c:if test="${not empty param.scp}"> + <c:param name="scp" value="${param.scp}"/> + </c:if> +</c:url> + +<c:url var="selfPaAction" value="/admin/role/RoleAdmin.do"> + <c:param name="mode" value="addLdapGroups"/> + <c:param name="r" value="${Role.id}"/> + <c:if test="${not empty param.pna}"> + <c:param name="pna" value="${param.pna}"/> + </c:if> + <c:if test="${not empty param.psa}"> + <c:param name="psa" value="${param.psa}"/> + </c:if> + <c:if test="${not empty param.pnp}"> + <c:param name="pnp" value="${param.pnp}"/> + </c:if> + <c:if test="${not empty param.psp}"> + <c:param name="psp" value="${param.psp}"/> + </c:if> + <c:if test="${not empty param.sop}"> + <c:param name="sop" value="${param.sop}"/> + </c:if> + <c:if test="${not empty param.scp}"> + <c:param name="scp" value="${param.scp}"/> + </c:if> +</c:url> + +<c:url var="selfPpAction" value="/admin/role/RoleAdmin.do"> + <c:param name="mode" value="addLdapGroups"/> + <c:param name="r" value="${Role.id}"/> + <c:if test="${not empty param.pna}"> + <c:param name="pna" value="${param.pna}"/> + </c:if> + <c:if test="${not empty param.psa}"> + <c:param name="psa" value="${param.psa}"/> + </c:if> + <c:if test="${not empty param.soa}"> + <c:param name="soa" value="${param.soa}"/> + </c:if> + <c:if test="${not empty param.sca}"> + <c:param name="sca" value="${param.sca}"/> + </c:if> + <c:if test="${not empty param.pnp}"> + <c:param name="pnp" value="${param.pnp}"/> + </c:if> + <c:if test="${not empty param.psp}"> + <c:param name="psp" value="${param.psp}"/> + </c:if> +</c:url> + + +<!-- SELECT & ADD --> +<table width="100%" cellpadding="0" cellspacing="0" border="0"> + <tr> + <td width="50%" valign="top"> + +<tiles:insert definition=".header.tab"> + <tiles:put name="tabKey" value="admin.role.groups.GroupsTab"/> + <tiles:put name="useFromSideBar" value="true"/> +</tiles:insert> + + </td> + <td><html:img page="/images/spacer.gif" width="40" height="1" border="0"/></td> + <td> + +<tiles:insert definition=".header.tab"> + <tiles:put name="tabKey" value="admin.role.groups.AssignToRoleTab"/> + <tiles:put name="useToSideBar" value="true"/> +</tiles:insert> + + </td> + </tr> + <tr> + <!-- SELECT COLUMN --> + <td width="50%" valign="top"> + <!-- TABLED LIST CONTENTS (SELECT COLUMN) --> + <div id="<c:out value="${widgetInstanceName}"/>FromDiv"> + + <display:table padRows="true" rightSidebar="true" items="${AvailableResGrps}" var="group" action="${selfPaAction}" + postfix="a" + styleId="fromTable" width="100%" cellpadding="0" cellspacing="0" border="0"> + <display:column width="1%" property="id" title="<input type="checkbox" onclick="ToggleAll(this, widgetProperties)" name="fromToggleAll">" isLocalizedTitle="false" styleClass="ListCellCheckbox" headerStyleClass="ListHeaderCheckbox"> + <display:checkboxdecorator name="availableGroup" onclick="ToggleSelection(this, widgetProperties)" styleClass="availableListMember"/> + </display:column> + <display:column property="name" title="common.header.Group" sortAttr="lg.name" width="50%"/> + <display:column property="description" title="common.header.Description" sortAttr="lg.description" width="50%"/> + </display:table> + + </div> + <!-- / --> + +<tiles:insert definition=".toolbar.new"> + <tiles:put name="useFromSideBar" value="true"/> + <tiles:put name="pageList" beanName="AvailableResGrps"/> + <tiles:put name="pageAction" beanName="selfPsaAction"/> + <tiles:put name="postfix" value="a"/> +</tiles:insert> + + </td> + <!-- / SELECT COLUMN --> + + <!-- ADD/REMOVE COLUMN --> + <td id="<c:out value="${widgetInstanceName}"/>AddRemoveButtonTd"> + <div id="AddButtonDiv" align="left"><html:img page="/images/fb_addarrow_gray.gif" border="0" titleKey="AddToList.ClickToAdd"/></div> + <br> <br> + <div id="RemoveButtonDiv" align="right"><html:img page="/images/fb_removearrow_gray.gif" border="0" titleKey="AddToList.ClickToRemove"/></div> + </td> + <!-- / ADD/REMOVE COLUMN --> + + <!-- ADD COLUMN --> + <td width="50%" valign="top"> + <!-- TABLED LIST CONTENTS (SELECT COLUMN) --> + <div id='<c:out value="${widgetInstanceName}"/>ToDiv'> + + <display:table padRows="true" leftSidebar="true" items="${PendingResGrps}" var="group" action="${selfPpAction}" + postfix="p" + styleId="toTable" width="100%" cellpadding="0" cellspacing="0" border="0"> + <display:column width="1%" property="id" title="<input type="checkbox" onclick="ToggleAll(this, widgetProperties)" name="toToggleAll">" isLocalizedTitle="false" styleClass="ListCellCheckbox" headerStyleClass="ListHeaderCheckbox"> + <display:checkboxdecorator name="pendingGroup" onclick="ToggleSelection(this, widgetProperties)" styleClass="pendingListMember"/> + </display:column> + <display:column property="name" title="common.header.Group" sortAttr="lg.name" width="50%"/> + <display:column property="description" title="common.header.Description" width="50%" sortAttr="lg.description"/> + </display:table> + + </div> + <!-- / --> + +<tiles:insert definition=".toolbar.new"> + <tiles:put name="newButtonKey" value="admin.role.groups.NewResourceGroupButton"/> + <tiles:put name="useToSideBar" value="true"/> + <tiles:put name="pageList" beanName="PendingResGrps"/> + <tiles:put name="pageAction" beanName="selfPspAction"/> + <tiles:put name="postfix" value="p"/> +</tiles:insert> + + </td> + <!-- / ADD COLUMN --> + + </tr> +</table> +<!-- / SELECT & ADD --> diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManager.java index 0478fd8..e372777 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManager.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManager.java @@ -208,8 +208,10 @@ public class LdapGroupManager { } Map<String, String> entry = new HashMap<String, String>(); String name = (String) si.getAttributes().get("cn").get(); + name = name.trim(); Attribute desc = si.getAttributes().get("description"); String description = desc != null ? (String) desc.get() : ""; + description = description.trim(); entry.put("id", name); entry.put("name", name); entry.put("description", description);
rhq-commits@lists.fedorahosted.org