/* * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2004, 2005, 2006], Hyperic, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License as * published by the Free Software Foundation. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ package org.hyperic.hq.ui.action.resource.group.inventory; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts2.interceptor.validation.SkipValidation; import org.hyperic.hq.appdef.shared.AppSvcClustDuplicateAssignException; import org.hyperic.hq.appdef.shared.AppdefEntityConstants; import org.hyperic.hq.appdef.shared.AppdefEntityID; import org.hyperic.hq.appdef.shared.AppdefGroupNotFoundException; import org.hyperic.hq.appdef.shared.AppdefGroupValue; import org.hyperic.hq.appdef.shared.AppdefResourceValue; import org.hyperic.hq.appdef.shared.ApplicationValue; // import org.hyperic.hq.authz.server.session.Resource; import org.hyperic.hq.authz.server.session.ResourceGroup; import org.hyperic.hq.authz.shared.AuthzConstants; import org.hyperic.hq.authz.shared.ResourceGroupManager; import org.hyperic.hq.authz.shared.ResourceManager; import org.hyperic.hq.bizapp.shared.AppdefBoss; import org.hyperic.hq.common.VetoException; import org.hyperic.hq.ui.Constants; import org.hyperic.hq.ui.action.resource.ResourceControllerNG; import org.hyperic.hq.ui.util.BizappUtilsNG; import org.hyperic.hq.ui.util.RequestUtils; import org.hyperic.hq.ui.util.SessionUtils; import org.hyperic.util.pager.PageControl; import org.hyperic.util.pager.PageList; import org.hyperic.util.pager.Pager; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import com.opensymphony.xwork2.ModelDriven; /** * An Action that adds Resources to a Group in the BizApp. This is first created * with AddGroupResourcesFormPrepareAction, which creates the list of pending * Resources to add to the group. * * Heavily based on: * * @see org.hyperic.hq.ui.action.resource.group.inventory.AddGroupResourcesFormPrepareAction */ @Component("addGroupResourcesActionNG") @Scope(value = "prototype") public class AddGroupResourcesActionNG extends ResourceControllerNG implements ModelDriven<AddGroupResourcesFormNG> { private final Log log = LogFactory.getLog(AddGroupResourcesActionNG.class); @Resource private ResourceGroupManager resourceGroupManager; @Resource private ResourceManager resourceManager; @Resource private AppdefBoss appdefBoss; private AddGroupResourcesFormNG addForm = new AddGroupResourcesFormNG(); private String internalEid; private String type; private String rid; private String internalNameFilter; private String internalFilterBy; /** * Add roles to the user specified in the given * <code>AddGroupResourcesForm</code>. */ @SkipValidation public String start() throws Exception { request = getServletRequest(); findAndSetResource(request, response); setHeaderResources(); try { Integer groupId = addForm.getRid(); PageControl pcPending; if (groupId == null) { groupId = RequestUtils.getResourceId(request); } int sessionId = RequestUtils.getSessionIdInt(request); PageControl pcAvail = RequestUtils.getPageControl(request, "psa", "pna", "soa", "sca"); pcPending = RequestUtils.getPageControl(request, "psp", "pnp", "sop", "scp"); AppdefGroupValue group = (AppdefGroupValue) RequestUtils .getResource(request); if (group == null) { addActionError(getText("resource.group.inventory.error.GroupNotFound")); return Constants.FAILURE_URL; } RequestUtils.setResource(request, group); addForm.setRid(group.getId()); log.trace("available page control: " + pcAvail); log.trace("pending page control: " + pcPending); log.trace("getting group [" + groupId + "]"); // XXX: if group == null, throw AppdefGroupNotFoundException /* * pending resources are those on the right side of the * "add to list" widget- awaiting association with the group when * the form's "ok" button is clicked. */ List<String> pendingResourceIds = SessionUtils.getListAsListStr( request.getSession(), Constants.PENDING_RESOURCES_SES_ATTR); String nameFilter = RequestUtils.getStringParameter(request, "nameFilter", null); log.trace("getting pending resources for group [" + groupId + "]"); List<AppdefEntityID> entities = BizappUtilsNG.buildAppdefEntityIds(pendingResourceIds); AppdefEntityID[] pendingResItems; if (entities.size() > 0) { pendingResItems = new AppdefEntityID[entities.size()]; entities.toArray(pendingResItems); } else { pendingResItems = null; } List<AppdefResourceValue> pendingResources = BizappUtilsNG .buildAppdefResources(sessionId, appdefBoss, pendingResItems); List<AppdefResourceValue> sortedPendingResource = BizappUtilsNG .sortAppdefResource(pendingResources, pcPending); PageList<AppdefResourceValue> pendingList = new PageList<AppdefResourceValue>(); pendingList.setTotalSize(sortedPendingResource.size()); Pager pendingPager = Pager.getDefaultPager(); pendingList = pendingPager.seek(sortedPendingResource, pcPending.getPagenum(), pcPending.getPagesize()); request.setAttribute(Constants.PENDING_RESOURCES_ATTR, pendingList); request.setAttribute(Constants.NUM_PENDING_RESOURCES_ATTR, new Integer(sortedPendingResource.size())); /* * available resources are all resources in the system that are not * associated with the user and are not pending */ log.trace("getting available resources for group [" + groupId + "]"); String filterBy = addForm.getFilterBy(); internalFilterBy = filterBy; int appdefType = -1; if (filterBy != null && !filterBy.equalsIgnoreCase("")) { appdefType = Integer.parseInt(filterBy); } PrepareResourceGroup p; if (group.isGroupCompat()) p = new PrepareCompatGroup(); else if (group.getGroupType() == AppdefEntityConstants.APPDEF_TYPE_GROUP_ADHOC_APP) p = new PrepareApplicationGroup(); else if (group.getGroupType() == AppdefEntityConstants.APPDEF_TYPE_GROUP_ADHOC_GRP) p = new PrepareGroupOfGroups(); else p = new PrepareMixedGroup(); p.loadGroupMembers(sessionId, addForm, group, appdefBoss, appdefType, nameFilter, pendingResItems, pcAvail); PageList availResources = p.getAvailResources(); request.setAttribute(Constants.AVAIL_RESOURCES_ATTR, availResources); request.setAttribute(Constants.NUM_AVAIL_RESOURCES_ATTR, new Integer(availResources.getTotalSize())); } catch (Exception e) { log.error(e); } return "loadAddGroupResources"; } public String save() throws Exception { request = getServletRequest(); Integer rid=addForm.getRid(); Integer entityType=addForm.getType(); internalEid=entityType+":"+rid; HttpSession session = request.getSession(); AppdefEntityID aeid = new AppdefEntityID(addForm.getType().intValue(), addForm.getRid()); request.setAttribute(Constants.ENTITY_ID_PARAM, aeid.getAppdefKey()); request.setAttribute(Constants.ACCORDION_PARAM, "1"); request.setAttribute(Constants.RESOURCE_PARAM, addForm.getRid() .toString()); request.setAttribute(Constants.RESOURCE_TYPE_ID_PARAM, addForm .getType().toString()); internalNameFilter = addForm.getNameFilter(); internalFilterBy = addForm.getFilterBy(); try { String forward = checkSubmit(addForm); if (forward != null) { if ( forward.equalsIgnoreCase("CANCEL") ) { log.trace("removing pending group list"); SessionUtils.removeList(session, Constants.PENDING_RESOURCES_SES_ATTR); } else if (forward.equalsIgnoreCase("ADDED")) { log.trace("adding to pending group list"); SessionUtils.addToList(session, Constants.PENDING_RESOURCES_SES_ATTR, addForm.getAvailableResources()); } else if (forward.equalsIgnoreCase("REMOVED")) { log.trace("removing from pending group list"); SessionUtils.removeFromList(session, Constants.PENDING_RESOURCES_SES_ATTR, addForm.getPendingResources()); } return forward; } Integer sessionId = RequestUtils.getSessionId(request); log.trace("getting pending resource list"); List<String> pendingResourceIds = SessionUtils.getListAsListStr( request.getSession(), Constants.PENDING_RESOURCES_SES_ATTR); if (pendingResourceIds.size() == 0) { return SUCCESS; } log.trace("getting group [" + aeid.getID() + "]"); AppdefGroupValue agroup = appdefBoss.findGroup( sessionId.intValue(), aeid.getId()); ResourceGroup group = appdefBoss.findGroupById( sessionId.intValue(), agroup.getId()); List<AppdefEntityID> newIds = new ArrayList<AppdefEntityID>(); for (String id : pendingResourceIds) { AppdefEntityID entity = new AppdefEntityID(id); org.hyperic.hq.authz.server.session.Resource r = resourceManager.findResource(entity); if (!resourceGroupManager.isMember(group, r)) { newIds.add(entity); } } // XXX: We have the list of resources above. Should use this // instead of passing in IDs.. waste of effort. appdefBoss.addResourcesToGroup(sessionId.intValue(), group, newIds); log.trace("removing pending user list"); SessionUtils.removeList(session, Constants.PENDING_RESOURCES_SES_ATTR); addActionMessage(getText("resource.group.inventory.confirm.AddResources")); return SUCCESS; } catch (AppSvcClustDuplicateAssignException e1) { log.debug("group update failed:", e1); addActionError(getText("ERR_DUP_CLUSTER_ASSIGNMENT")); return INPUT; } catch (AppdefGroupNotFoundException e) { addActionError(getText("resource.common.inventory.error.ResourceNotFound")); return INPUT; } catch (VetoException ve) { addActionError(getText( "resource.group.inventory.error.UpdateResourceListVetoed", new String[] { ve.getMessage() } )); return INPUT; } } @SkipValidation public String cancel() throws Exception { setHeaderResources(); HttpSession session = this.request.getSession(); clearErrorsAndMessages(); this.clearCustomErrorMessages(); if ( addForm.getType()!=null && addForm.getRid()!= null ) { internalEid = addForm.getType() + ":" + addForm.getRid(); } else { AppdefEntityID aeid = RequestUtils.getEntityId(this.request); if (aeid!=null) { setEntityRequestParams(aeid); } } log.trace("removing pending group list"); SessionUtils.removeList(session, Constants.PENDING_RESOURCES_SES_ATTR); return "cancel"; } @SkipValidation public String reset() throws Exception { setHeaderResources(); HttpSession session = this.request.getSession(); addForm.reset(); clearErrorsAndMessages(); this.clearCustomErrorMessages(); AppdefEntityID aeid = null; if (addForm.getType() != null && addForm.getRid()!= null) { aeid = new AppdefEntityID(addForm.getType().intValue(), addForm.getRid()); } else { aeid = RequestUtils.getEntityId(this.request); } if (aeid!= null) { setEntityRequestParams(aeid); } SessionUtils.removeList(session, Constants.PENDING_RESOURCES_SES_ATTR); return "reset"; } private void setEntityRequestParams (AppdefEntityID eid) { this.internalEid = eid.toString(); this.rid = eid.getId().toString(); this.type = String.valueOf( eid.getType() ); } public AddGroupResourcesFormNG getAddForm() { return addForm; } public void setAddForm(AddGroupResourcesFormNG addForm) { this.addForm = addForm; } public String getInternalEid() { return internalEid; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getRid() { return rid; } public void setRid(String rid) { this.rid = rid; } public void setInternalEid(String internalEid) { this.internalEid = internalEid; } public AddGroupResourcesFormNG getModel() { return addForm; } private abstract class PrepareResourceGroup { /** * @return a list of available resources. */ protected abstract PageList getAvailResources(); /** * This method loads group members from the back-end. */ protected abstract void loadGroupMembers(int sessionId, AddGroupResourcesFormNG addForm, AppdefGroupValue group, AppdefBoss boss, int appdefType, String nameFilter, AppdefEntityID[] pendingResItems, PageControl pcAvail) throws Exception; } /** * inner class which represents the Compatible groups. */ private class PrepareCompatGroup extends PrepareResourceGroup { private PageList avail = null; protected PageList getAvailResources() { return avail; } protected void loadGroupMembers(int sessionId, AddGroupResourcesFormNG addForm, AppdefGroupValue group, AppdefBoss boss, int appdefType, String nameFilter, AppdefEntityID[] pendingResItems, PageControl pcAvail) throws Exception { avail = boss.findCompatInventory(sessionId, group.getGroupEntType(), group.getGroupEntResType(), group.getEntityId(), pendingResItems, nameFilter, pcAvail); } } /** * prepares a Group of Groups */ private class PrepareApplicationGroup extends PrepareResourceGroup { PageList availMembers = null; protected PageList getAvailResources() { return availMembers; } protected void loadGroupMembers(int sessionId, AddGroupResourcesFormNG addForm, AppdefGroupValue group, AppdefBoss boss, int appdefType, String nameFilter, AppdefEntityID[] pendingResItems, PageControl pcAvail) throws Exception { if (appdefType == -1) appdefType = AppdefEntityConstants.APPDEF_TYPE_APPLICATION; availMembers = boss.findCompatInventory(sessionId, appdefType, -1, group.getEntityId(), pendingResItems, null, pcAvail); } } /** * Inner class which represents the Group of Groups. */ private class PrepareGroupOfGroups extends PrepareResourceGroup { PageList availMembers = new PageList(); protected PageList getAvailResources() { return availMembers; } protected void loadGroupMembers(int sessionId, AddGroupResourcesFormNG addForm, AppdefGroupValue group, AppdefBoss boss, int appdefType, String nameFilter, AppdefEntityID[] pendingResItems, PageControl pcAvail) throws Exception { if (appdefType == -1) appdefType = AppdefEntityConstants.APPDEF_TYPE_GROUP_ADHOC_APP; PageList<AppdefResourceValue> compatGroups = boss .findCompatInventory(sessionId, AppdefEntityConstants.APPDEF_TYPE_GROUP, appdefType, group.getEntityId(), pendingResItems, null, pcAvail); for (AppdefResourceValue compatGroup : compatGroups) { if (!compatGroup.getName().equals( AuthzConstants.rootResourceGroupName) && !compatGroup.getName().equals( AuthzConstants.groupResourceTypeName)) { availMembers.add(compatGroup); } } /** * load the group type filters */ addForm.setAvailResourceTypes(buildGroupTypes()); } } /** * inner class representing the Mixed Group of PSS */ private class PrepareMixedGroup extends PrepareResourceGroup { PageList filteredAvailList = null; protected PageList getAvailResources() { return filteredAvailList; } protected void loadGroupMembers(int sessionId, AddGroupResourcesFormNG addForm, AppdefGroupValue group, AppdefBoss boss, int appdefType, String nameFilter, AppdefEntityID[] pendingResItems, PageControl pcAvail) throws Exception { if (appdefType == -1) appdefType = AppdefEntityConstants.APPDEF_TYPE_PLATFORM; filteredAvailList = boss.findCompatInventory(sessionId, appdefType, -1, group.getEntityId(), pendingResItems, nameFilter, pcAvail); /** * load the resource type filters */ addForm.setAvailResourceTypes(buildResourceTypes()); } } protected void findAndSetResource(HttpServletRequest request, HttpServletResponse response) throws Exception { AppdefEntityID aeid = setResource(); // If this is a cluster, then it's possible that it's also part of an // application Integer sessionId = RequestUtils.getSessionId(request); PageList<ApplicationValue> appValues = appdefBoss.findApplications( sessionId.intValue(), aeid, PageControl.PAGE_ALL); if (appValues.getTotalSize() > 0) { request.setAttribute(Constants.APPLICATIONS_ATTR, appValues); } } public String getInternalNameFilter() { return internalNameFilter; } public void setInternalNameFilter(String internalNameFilter) { this.internalNameFilter = internalNameFilter; } public String getInternalFilterBy() { return internalFilterBy; } public void setInternalFilterBy(String internalFilterBy) { this.internalFilterBy = internalFilterBy; } /** * builds a list of resource types (platform, server, service). * * @return a list of group types from the list */ private Map<String,String> buildResourceTypes() { LinkedHashMap<String,String> gTypes = new LinkedHashMap<String,String>(); int type = -1; type = AppdefEntityConstants.APPDEF_TYPE_PLATFORM; gTypes.put(Integer.toString(type),AppdefEntityConstants.typeToString(type)); type = AppdefEntityConstants.APPDEF_TYPE_SERVER; gTypes.put(Integer.toString(type),AppdefEntityConstants.typeToString(type)); type = AppdefEntityConstants.APPDEF_TYPE_SERVICE; gTypes.put(Integer.toString(type),AppdefEntityConstants.typeToString(type)); return gTypes; } /** * builds a unique list of group types. * * @return a unique list of group types from the list */ private Map<String,String> buildGroupTypes() { LinkedHashMap<String,String> gTypes = new LinkedHashMap<String,String>(); int type = -1; type = AppdefEntityConstants.APPDEF_TYPE_GROUP_ADHOC_APP; gTypes.put(Integer.toString(type),AppdefEntityConstants.getAppdefGroupTypeName(type)); type = AppdefEntityConstants.APPDEF_TYPE_GROUP_ADHOC_PSS; gTypes.put(Integer.toString(type),AppdefEntityConstants.getAppdefGroupTypeName(type)); type = AppdefEntityConstants.APPDEF_TYPE_GROUP_COMPAT_PS; gTypes.put(Integer.toString(type),AppdefEntityConstants.getAppdefGroupTypeName(type)); return gTypes; } }