Author: scottmf Date: 2010-04-08 12:15:40 -0700 (Thu, 08 Apr 2010) New Revision: 14487 URL: http://svn.hyperic.org/?view=rev&root=Hyperic+HQ&revision=14487 Added: trunk/unittest/data/resourceManagerTests.README trunk/unittest/data/resourceManagerTests.xml.gz trunk/unittest/src/org/hyperic/hq/authz/server/session/ResourceManagerTest.java trunk/unittest/src/org/hyperic/hq/authz/server/session/ResourceManagerTestEJBImpl.java Modified: trunk/src/org/hyperic/hq/authz/server/session/ResourceDAO.java trunk/src/org/hyperic/hq/authz/server/session/ResourceManagerEJBImpl.java trunk/src/org/hyperic/hq/bizapp/server/session/AppdefBossEJBImpl.java Log: [HHQ-3564] optimize code and query around ResourceManager.findViewableSvcResources() Modified: trunk/src/org/hyperic/hq/authz/server/session/ResourceDAO.java =================================================================== --- trunk/src/org/hyperic/hq/authz/server/session/ResourceDAO.java 2010-04-08 07:53:36 UTC (rev 14486) +++ trunk/src/org/hyperic/hq/authz/server/session/ResourceDAO.java 2010-04-08 19:15:40 UTC (rev 14487) @@ -29,6 +29,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.TreeSet; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; @@ -231,48 +232,45 @@ .list(); } - public Collection findViewableSvcRes_orderName(Integer user, - Boolean fSystem) - { - // we use join here to produce a single - // join => the strategy here is to rely on - // the database query optimizer to optimize the query - // by feeding it a single query. - // - // The important point is we should first give the - // opportunity to the database to do the "query" optimization - // before we do anything else. - // Note: this should be refactored to use named queries so - // that we can perform "fetch" optimization outside of the code - String sql = - "select r from Resource r join r.resourceType rt " + - "where r.system = :system and exists " + - "(select rg from GroupMember g " + - " join g.group rg " + - " join g.resource rs " + - "where ((rg.resource = r and rg.groupType = 15) or " + - "(rt.name = :resSvcType and r = rs)) " + - " and (r.owner.id = :subjId or exists " + - "(select role from rg.roles role " + - "join role.subjects subj " + - "join role.operations op " + - "where subj.id = :subjId and " + - "op.name = case rt.name " + - "when (:resSvcType) then '" + - AuthzConstants.serviceOpViewService + - "' " + - "else '" + - AuthzConstants.groupOpViewResourceGroup + - "' end))) " + - "order by r.sortName"; + public Collection findViewableSvcRes_orderName(Integer user, Boolean fSystem) { + ResourceTypeDAO rDao = DAOFactory.getDAOFactory().getResourceTypeDAO(); + ResourceType serviceType = rDao.findByName(AuthzConstants.serviceResType); + OperationDAO opDao = getOperationDAO(); + Operation op = opDao.findByTypeAndName(serviceType, AuthzConstants.serviceOpViewService); + final String sql = new StringBuilder(1024) + .append("SELECT {res.*} ") + .append("FROM EAM_SUBJECT subject ") + .append("JOIN EAM_SUBJECT_ROLE_MAP subjrolemap on subject.ID = subjrolemap.SUBJECT_ID ") + .append("JOIN EAM_ROLE role on role.ID = subjrolemap.ROLE_ID ") + .append("JOIN EAM_ROLE_RESOURCE_GROUP_MAP rolegrpmap on rolegrpmap.ROLE_ID = role.ID ") + .append("JOIN EAM_RESOURCE res on res.RESOURCE_TYPE_ID = :resourceTypeId ") + .append("AND res.FSYSTEM = :system ") + .append("JOIN EAM_RES_GRP_RES_MAP grpmap on grpmap.RESOURCE_ID = res.ID ") + .append("JOIN EAM_RESOURCE_GROUP resgrp on resgrp.ID = grpmap.RESOURCE_GROUP_ID ") + .append("AND rolegrpmap.RESOURCE_GROUP_ID = resgrp.ID ") + .append("JOIN EAM_ROLE_OPERATION_MAP opmap on role.id = opmap.ROLE_ID ") + .append("AND opmap.OPERATION_ID = :opId ") + .append("WHERE subject.ID = :subjectId ") + .append("UNION ALL ") + .append("SELECT {res.*} ") + .append("FROM EAM_RESOURCE res ") + .append("WHERE res.SUBJECT_ID = :subjectId AND res.RESOURCE_TYPE_ID = :resourceTypeId ") + .append("AND res.FSYSTEM = :system ") + .toString(); List resources = - getSession().createQuery(sql) + getSession().createSQLQuery(sql) + .addEntity("res", Resource.class) .setBoolean("system", fSystem.booleanValue()) - .setInteger("subjId", user.intValue()) - .setString("resSvcType", AuthzConstants.serviceResType) + .setInteger("opId", op.getId().intValue()) + .setInteger("subjectId", user.intValue()) + .setInteger("resourceTypeId", serviceType.getId().intValue()) .list(); + // use TreeSet to eliminate dups and sort by Resource + return new TreeSet(resources); + } - return resources; + private OperationDAO getOperationDAO() { + return new OperationDAO(DAOFactory.getDAOFactory()); } public Collection findSvcRes_orderName(Boolean fSystem) Modified: trunk/src/org/hyperic/hq/authz/server/session/ResourceManagerEJBImpl.java =================================================================== --- trunk/src/org/hyperic/hq/authz/server/session/ResourceManagerEJBImpl.java 2010-04-08 07:53:36 UTC (rev 14486) +++ trunk/src/org/hyperic/hq/authz/server/session/ResourceManagerEJBImpl.java 2010-04-08 19:15:40 UTC (rev 14487) @@ -28,6 +28,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -56,13 +57,11 @@ import org.hyperic.hq.appdef.shared.ApplicationNotFoundException; import org.hyperic.hq.appdef.shared.PlatformManagerLocal; import org.hyperic.hq.appdef.shared.PlatformNotFoundException; +import org.hyperic.hq.appdef.shared.ResourcesCleanupZevent; import org.hyperic.hq.appdef.shared.ServerManagerLocal; import org.hyperic.hq.appdef.shared.ServerNotFoundException; import org.hyperic.hq.appdef.shared.ServiceManagerLocal; import org.hyperic.hq.appdef.shared.ServiceNotFoundException; -import org.hyperic.hq.authz.server.session.AuthzSubject; -import org.hyperic.hq.authz.server.session.Resource; -import org.hyperic.hq.authz.server.session.ResourceType; import org.hyperic.hq.authz.shared.AuthzConstants; import org.hyperic.hq.authz.shared.PermissionException; import org.hyperic.hq.authz.shared.PermissionManager; @@ -70,11 +69,11 @@ import org.hyperic.hq.authz.shared.ResourceEdgeCreateException; import org.hyperic.hq.authz.shared.ResourceManagerLocal; import org.hyperic.hq.authz.shared.ResourceManagerUtil; +import org.hyperic.hq.bizapp.server.session.AppdefBossEJBImpl; import org.hyperic.hq.common.SystemException; import org.hyperic.hq.common.VetoException; import org.hyperic.hq.common.server.session.ResourceAudit; import org.hyperic.hq.zevents.ZeventManager; -import org.hyperic.util.StringUtil; import org.hyperic.util.pager.PageControl; import org.hyperic.util.pager.PageList; import org.hyperic.util.pager.Pager; @@ -625,39 +624,33 @@ * @return PageList of resource values * @ejb:interface-method */ - public PageList findViewableSvcResources(AuthzSubject subject, - String resourceName, + public PageList findViewableSvcResources(AuthzSubject subject, String nameFilter, PageControl pc) { - Collection resources; - AuthzSubject subj = getSubjectDAO().findById(subject.getId()); pc = PageControl.initDefaults(pc, SortAttribute.RESOURCE_NAME); PermissionManager pm = PermissionManagerFactory.getInstance(); - // Damn I love this code. -- JMT - switch(pc.getSortattribute()) { - case SortAttribute.RESOURCE_NAME: - default: - resources = pm.findServiceResources(subj, Boolean.FALSE); - break; - } + // returns a sorted Collection by resourceName + Collection resources = pm.findServiceResources(subj, Boolean.FALSE); - // TODO: Move filtering into EJBQL - ArrayList ordResources = new ArrayList(resources.size()); - for (Iterator it = resources.iterator(); it.hasNext();) { - Resource res = (Resource) it.next(); - - if (StringUtil.stringDoesNotExist(res.getName(), resourceName)) - continue; - - if (pc.isDescending()) // Add to head of array list - ordResources.add(0, res); - else // Add to tail of array list - ordResources.add(res); + if (nameFilter != null) { + for (Iterator it=resources.iterator(); it.hasNext(); ) { + Resource r = (Resource) it.next(); + if (r == null || r.isInAsyncDeleteState() || + !r.getName().toLowerCase().contains(nameFilter.toLowerCase())) { + it.remove(); + } + } } + Collection ordResources = resources; + if (pc.isDescending()) { + ordResources = new ArrayList(resources); + Collections.reverse((List)ordResources); + } + return new PageList(ordResources, ordResources.size()); } Modified: trunk/src/org/hyperic/hq/bizapp/server/session/AppdefBossEJBImpl.java =================================================================== --- trunk/src/org/hyperic/hq/bizapp/server/session/AppdefBossEJBImpl.java 2010-04-08 07:53:36 UTC (rev 14486) +++ trunk/src/org/hyperic/hq/bizapp/server/session/AppdefBossEJBImpl.java 2010-04-08 19:15:40 UTC (rev 14487) @@ -118,7 +118,6 @@ import org.hyperic.hq.appdef.shared.pager.AppdefPagerFilterExclude; import org.hyperic.hq.appdef.shared.pager.AppdefPagerFilterGroupEntityResource; import org.hyperic.hq.appdef.shared.pager.AppdefPagerFilterGroupMemExclude; -import org.hyperic.hq.application.HQApp; import org.hyperic.hq.auth.shared.SessionException; import org.hyperic.hq.auth.shared.SessionManager; import org.hyperic.hq.auth.shared.SessionNotFoundException; @@ -139,7 +138,6 @@ import org.hyperic.hq.authz.shared.ResourceManagerLocal; import org.hyperic.hq.autoinventory.AutoinventoryException; import org.hyperic.hq.autoinventory.ScanConfigurationCore; -import org.hyperic.hq.bizapp.shared.AIBossLocal; import org.hyperic.hq.bizapp.shared.AllConfigResponses; import org.hyperic.hq.bizapp.shared.AppdefBossLocal; import org.hyperic.hq.bizapp.shared.AppdefBossUtil; @@ -186,7 +184,6 @@ import org.hyperic.util.pager.Pager; import org.hyperic.util.pager.SortAttribute; import org.hyperic.util.timer.StopWatch; - import org.quartz.SchedulerException; /** @@ -3219,16 +3216,16 @@ public PageList findAvailableServicesForApplication(int sessionId, Integer appId, AppdefEntityID[] pendingEntities, - String resourceName, PageControl pc) + String nameFilter, PageControl pc) throws AppdefEntityNotFoundException, PermissionException, SessionException { - List toBePaged, filterList, authzResources; + final StopWatch watch = new StopWatch(); + final boolean debug = log.isDebugEnabled(); AuthzSubject subject = manager.getSubject(sessionId); // init our (never-null) page and filter lists - toBePaged = new ArrayList(); - filterList = new ArrayList(); + List filterList = new ArrayList(); // add a pager filter for removing pending appdef entities if (pendingEntities != null) { @@ -3238,48 +3235,52 @@ int oriPageSize = pc.getPagesize(); pc.setPagesize( PageControl.SIZE_UNLIMITED ); - authzResources = getResourceManager() - .findViewableSvcResources(subject, resourceName, pc); + if (debug) watch.markTimeBegin("findViewableSvcResources"); + Set authzResources = + new TreeSet(getResourceManager().findViewableSvcResources(subject, nameFilter, pc)); + if (debug) watch.markTimeEnd("findViewableSvcResources"); + int authzResourcesSize = authzResources.size(); + pc.setPagesize( oriPageSize ); // Remove existing application assigned inventory - List assigned = findServiceInventoryByApplication(sessionId, appId, - PageControl.PAGE_ALL); - for (int x = 0; x < assigned.size(); x++) { - assigned.set(x, ((AppdefResourceValue) assigned.get(x)) - .getEntityId()); + if (debug) watch.markTimeBegin("findServiceInventoryByApplication"); + List assigned = findServiceInventoryByApplication(sessionId, appId, PageControl.PAGE_ALL); + if (debug) watch.markTimeEnd("findServiceInventoryByApplication"); + if (debug) watch.markTimeBegin("loop1"); + ResourceManagerLocal rMan = getResourceManager(); + for (Iterator it=assigned.iterator(); it.hasNext(); ) { + AppdefResourceValue val = (AppdefResourceValue) it.next(); + authzResources.remove(rMan.findResource(val.getEntityId())); } + if (debug) watch.markTimeEnd("loop1"); - for (Iterator i = authzResources.iterator(); i.hasNext();) { - Resource rv = (Resource) i.next(); - AppdefEntityID id = new AppdefEntityID(rv); - if (!assigned.contains(id)) { - toBePaged.add(id); - } + List toBePaged = new ArrayList(authzResources.size()); + for (Iterator it=authzResources.iterator(); it.hasNext(); ) { + Resource r = (Resource) it.next(); + toBePaged.add(new AppdefEntityID(r)); } // Page it, then convert to AppdefResourceValue - List finalList = new ArrayList(); + List finalList = new ArrayList(authzResources.size()); PageList pl = getPageList (toBePaged, pc, filterList); - for (Iterator itr = pl.iterator();itr.hasNext();){ - AppdefEntityID ent = (AppdefEntityID) itr.next(); + for (Iterator it=pl.iterator(); it.hasNext();){ + AppdefEntityID ent = (AppdefEntityID) it.next(); try { finalList.add( findById(subject,ent) ); } catch (AppdefEntityNotFoundException e) { // XXX - hack to ignore the error. This must have occurred when // we created the resource, and rolled back the AppdefEntity // but not the Resource - log.error("Invalid entity still in resource table: " + ent); + log.error("Invalid entity still in resource table: " + ent, e); } } - - int pendingSize = 0; - if (pendingEntities != null) - pendingSize = pendingEntities.length; - - int adjustedSize = authzResources.size() - pendingSize; - return new PageList(finalList,adjustedSize); + int pendingSize = (pendingEntities != null) ? pendingEntities.length : 0; + int adjustedSize = authzResourcesSize - pendingSize; + PageList rtn = new PageList(finalList,adjustedSize); + if (debug) log.debug(watch); + return rtn; } private PageList getPageList (Collection coll, PageControl pc) { Added: trunk/unittest/data/resourceManagerTests.README =================================================================== --- trunk/unittest/data/resourceManagerTests.README (rev 0) +++ trunk/unittest/data/resourceManagerTests.README 2010-04-08 19:15:40 UTC (rev 14487) @@ -0,0 +1,2 @@ +../../bin/exportTable.sh -l jdbc:mysql://localhost:3306/hqdb -u hqadmin -p hqadmin -d /home/scottmf/sts-workspace/hq_trunk/unittest/data/resourceManagerTests -t EAM_AGENT,EAM_AUDIT,EAM_CONFIG_RESPONSE,EAM_CRISPO,EAM_CRISPO_OPT,EAM_CRITERIA,EAM_DASH_CONFIG,EAM_MEASUREMENT,EAM_MEASUREMENT_CAT,EAM_MEASUREMENT_TEMPL,EAM_MONITORABLE_TYPE,EAM_OPERATION,EAM_PLATFORM,EAM_PLATFORM_SERVER_TYPE_MAP,EAM_PLATFORM_TYPE,EAM_RES_GRP_RES_MAP,EAM_RESOURCE,EAM_RESOURCE_EDGE,EAM_RESOURCE_GROUP,EAM_RESOURCE_RELATION,EAM_RESOURCE_TYPE,EAM_ROLE,EAM_ROLE_OPERATION_MAP,EAM_ROLE_RESOURCE_GROUP_MAP,EAM_SERVER,EAM_SERVER_TYPE,EAM_SERVICE,EAM_SERVICE_TYPE,EAM_SUBJECT,EAM_SUBJECT_ROLE_MAP,EAM_CONFIG_PROPS +# may want to think about exporting HQ_SEQUENCE as well when the testdb moves to mysql Added: trunk/unittest/data/resourceManagerTests.xml.gz =================================================================== (Binary files differ) Property changes on: trunk/unittest/data/resourceManagerTests.xml.gz ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/unittest/src/org/hyperic/hq/authz/server/session/ResourceManagerTest.java =================================================================== --- trunk/unittest/src/org/hyperic/hq/authz/server/session/ResourceManagerTest.java (rev 0) +++ trunk/unittest/src/org/hyperic/hq/authz/server/session/ResourceManagerTest.java 2010-04-08 19:15:40 UTC (rev 14487) @@ -0,0 +1,30 @@ +package org.hyperic.hq.authz.server.session; + +import org.hyperic.hq.authz.shared.ResourceManagerTestLocal; +import org.hyperic.util.unittest.server.BaseServerTestCase; +import org.hyperic.util.unittest.server.LocalInterfaceRegistry; + +public class ResourceManagerTest extends BaseServerTestCase { + + private static final String FILENAME = "resourceManagerTests.xml.gz"; + private LocalInterfaceRegistry _registry; + + public ResourceManagerTest(String name) { + super(name, true); + } + + public void setUp() throws Exception { + super.setUp(); + super.insertSchemaData(FILENAME); + _registry = deployHQ(); + } + + public void testFindViewableSvcResources() throws Exception { + ResourceManagerTestLocal resMan = (ResourceManagerTestLocal) + _registry.getLocalInterface( + ResourceManagerTestEJBImpl.class, + ResourceManagerTestLocal.class); + resMan.testFindViewableSvcResources(); + } + +} Added: trunk/unittest/src/org/hyperic/hq/authz/server/session/ResourceManagerTestEJBImpl.java =================================================================== --- trunk/unittest/src/org/hyperic/hq/authz/server/session/ResourceManagerTestEJBImpl.java (rev 0) +++ trunk/unittest/src/org/hyperic/hq/authz/server/session/ResourceManagerTestEJBImpl.java 2010-04-08 19:15:40 UTC (rev 14487) @@ -0,0 +1,80 @@ +package org.hyperic.hq.authz.server.session; + +import java.rmi.RemoteException; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import javax.ejb.CreateException; +import javax.ejb.EJBException; +import javax.ejb.SessionBean; +import javax.ejb.SessionContext; + +import junit.framework.Assert; + +import org.hyperic.dao.DAOFactory; +import org.hyperic.hq.authz.shared.AuthzSubjectManagerLocal; +import org.hyperic.hq.authz.shared.ResourceManagerLocal; +import org.hyperic.hq.authz.shared.ResourceManagerTestLocal; +import org.hyperic.hq.authz.shared.ResourceManagerTestUtil; +import org.hyperic.hq.common.SystemException; + +/** + * The session bean implementing the in-container unit tests for the + * AuthzSubjectManager. + * + * @ejb:bean name="ResourceManagerTest" + * jndi-name="ejb/authz/ResourceManagerTest" + * local-jndi-name="LocalResourceManagerTest" + * view-type="local" + * type="Stateless" + * + * @ejb:util generate="physical" + * @ejb:transaction type="NotSupported" + */ +public class ResourceManagerTestEJBImpl implements SessionBean { + /** + * @ejb:interface-method + */ + public void testFindViewableSvcResources() throws Exception { + testFindViewableSvcResources("joe", 15); + testFindViewableSvcResources("hqadmin", 1264); + testFindViewableSvcResources("nipuna11", 901); + testFindViewableSvcResources("nipuna2", 901); + testFindViewableSvcResources("nipuna3", 901); + testFindViewableSvcResources("guest", 15); + } + + private void testFindViewableSvcResources(String user, int expectedResources) { + AuthzSubjectManagerLocal authMan = AuthzSubjectManagerEJBImpl.getOne(); + AuthzSubject subj = authMan.findSubjectByName(user); + // it would be nice to test the Manager method rather than the DAO, but since it is an + // ee feature, it makes that a big more difficult. The Manager calls + // findViewableSvcRes_orderName() eventually anyway. + Collection list = getResourceDAO().findViewableSvcRes_orderName(subj.getId(), Boolean.FALSE); + // List list = getResourceMan().findViewableSvcResources(subj, null, PageControl.PAGE_ALL); + Set toTest = new HashSet(list); + Assert.assertEquals( + "There are duplicate service resources returned from findViewableSvcResources()", + list.size(), toTest.size()); + Assert.assertEquals(expectedResources, toTest.size()); + } + + private ResourceDAO getResourceDAO() { + return new ResourceDAO(DAOFactory.getDAOFactory()); + } + + public static ResourceManagerTestLocal getOne() { + try { + return ResourceManagerTestUtil.getLocalHome().create(); + } catch (Exception e) { + throw new SystemException(e); + } + } + + public void ejbCreate() throws CreateException {} + public void ejbActivate() throws EJBException, RemoteException {} + public void ejbPassivate() throws EJBException, RemoteException {} + public void ejbRemove() throws EJBException, RemoteException {} + public void setSessionContext(SessionContext arg0) {} +} |