package org.rhq.enterprise.server.discovery; import java.util.HashSet; import java.util.List; import java.util.Set; import org.rhq.core.clientapi.server.discovery.InventoryReport; import org.rhq.core.domain.criteria.ResourceTypeCriteria; import org.rhq.core.domain.plugin.Plugin; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.domain.util.PageList; import org.rhq.enterprise.server.auth.SubjectManagerLocal; import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal; import org.rhq.enterprise.server.resource.metadata.PluginManagerLocal; import org.rhq.enterprise.server.util.CriteriaQuery; import org.rhq.enterprise.server.util.CriteriaQueryExecutor; public class DeletedResourceTypeFilter { private SubjectManagerLocal subjectMgr; private ResourceTypeManagerLocal resourceTypeMgr; private PluginManagerLocal pluginMgr; private Set<String> deletedTypes; private Set<String> installedPlugins; public DeletedResourceTypeFilter(SubjectManagerLocal subjectManager, ResourceTypeManagerLocal resourceTypeManager, PluginManagerLocal pluginManager) { subjectMgr = subjectManager; resourceTypeMgr = resourceTypeManager; pluginMgr = pluginManager; deletedTypes = new HashSet<String>(); installedPlugins = new HashSet<String>(); loadDeletedTypes(); loadInstalledPlugins(); } private void loadDeletedTypes() { ResourceTypeCriteria criteria = new ResourceTypeCriteria(); criteria.addFilterDeleted(true); // we'll filter on all deleted types ... criteria.addFilterIgnored(null); // ... whether they are ignored or not //Use CriteriaQuery to automatically chunk/page through criteria query results CriteriaQueryExecutor<ResourceType, ResourceTypeCriteria> queryExecutor = new CriteriaQueryExecutor<ResourceType, ResourceTypeCriteria>() { @Override public PageList<ResourceType> execute(ResourceTypeCriteria criteria) { return resourceTypeMgr.findResourceTypesByCriteria(subjectMgr.getOverlord(), criteria); } }; CriteriaQuery<ResourceType, ResourceTypeCriteria> results = new CriteriaQuery<ResourceType, ResourceTypeCriteria>( criteria, queryExecutor); for (ResourceType type : results) { deletedTypes.add(type.getName() + "::" + type.getPlugin()); } } private void loadInstalledPlugins() { List<Plugin> plugins = pluginMgr.getInstalledPlugins(); for (Plugin plugin : plugins) { installedPlugins.add(plugin.getName()); } } public Set<ResourceType> apply(InventoryReport report) { Set<ResourceType> resourceTypes = getResourceTypes(report.getAddedRoots()); Set<ResourceType> staleTypes = new HashSet<ResourceType>(); for (ResourceType type : resourceTypes) { // We check two things to determine whether a report should be rejected. First we check // that the plugin from which the type comes is installed. We check that the plugin is // installed as opposed to checking that it is deleted because the plugin could also // be purged in which case checking against deleted plugins wouldn't catch it. Secondly, // we check to see if the type is a deleted type. Here we check against deleted types // instead of installed types because the number of deleted types at any given time // should be much smaller than the number of installed types, resulting in faster look // ups. If we have a stale type in the report and that type has already been purged from // the database, it will get flagged by the check against installed plugins. if (!installedPlugins.contains(type.getPlugin()) || deletedTypes.contains(type.getName() + "::" + type.getPlugin())) { staleTypes.add(type); } } return staleTypes; } private Set<ResourceType> getResourceTypes(Set<Resource> resources) { Set<ResourceType> types = new HashSet<ResourceType>(); for (Resource resource : resources) { types.add(resource.getResourceType()); types.addAll(getResourceTypes(resource.getChildResources())); } return types; } }