package org.rhq.enterprise.server.resource.metadata;
import java.util.Arrays;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.Property;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
import org.rhq.core.domain.configuration.definition.PropertyDefinition;
import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageControl;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.configuration.metadata.ConfigurationDefinitionUpdateReport;
import org.rhq.enterprise.server.configuration.metadata.ConfigurationMetadataManagerLocal;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
import org.rhq.enterprise.server.util.BatchIterator;
@Stateless
public class PluginConfigurationMetadataManagerBean implements PluginConfigurationMetadataManagerLocal {
private static Log log = LogFactory.getLog(PluginConfigurationMetadataManagerBean.class);
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
private EntityManager entityMgr;
@EJB
private ConfigurationMetadataManagerLocal configurationMetadataMgr;
@EJB
private PluginConfigurationMetadataManagerLocal pluginConfigurationMetadataMgr;
@EJB
private SubjectManagerLocal subjectMgr;
@EJB
private ResourceManagerLocal resourceMgr;
@Override
public void updatePluginConfigurationDefinition(ResourceType existingType, ResourceType newType) {
if (log.isDebugEnabled()) {
log.debug("Updating plugin configuration definition for " + existingType);
}
existingType = entityMgr.find(ResourceType.class, existingType.getId());
ConfigurationDefinition existingConfigurationDefinition = existingType.getPluginConfigurationDefinition();
if (newType.getPluginConfigurationDefinition() != null) {
// all new
if (existingConfigurationDefinition == null) {
if (log.isDebugEnabled()) {
log.debug(existingType + " currently does not have a plugin configuration definition. Adding "
+ "new plugin configuration.");
}
entityMgr.persist(newType.getPluginConfigurationDefinition());
existingType.setPluginConfigurationDefinition(newType.getPluginConfigurationDefinition());
} else { // update the configuration
if (log.isDebugEnabled()) {
log.debug("Updating plugin configuration definition for " + existingType);
}
ConfigurationDefinitionUpdateReport updateReport = configurationMetadataMgr
.updateConfigurationDefinition(newType.getPluginConfigurationDefinition(),
existingConfigurationDefinition);
if (updateReport.getNewPropertyDefinitions().size() > 0
|| updateReport.getUpdatedPropertyDefinitions().size() > 0) {
// don't pull/update every resource entity in at this point, do it in batches
List<Integer> resourceIds = resourceMgr.findIdsByTypeIds(Arrays.asList(existingType.getId()));
BatchIterator<Integer> batchIterator = new BatchIterator<Integer>(resourceIds, 200);
while (batchIterator.hasMoreBatches()) {
pluginConfigurationMetadataMgr.updateResourcePluginConfigurationsInNewTransaction(
batchIterator.getNextBatch(), updateReport);
}
}
}
} else {
// resourceType.getPlu... is null -> remove the existing config
if (existingConfigurationDefinition != null) {
if (log.isDebugEnabled()) {
log.debug("Removing plugin configuration definition for " + existingType);
}
existingType.setPluginConfigurationDefinition(null);
entityMgr.remove(existingConfigurationDefinition);
}
}
}
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void updateResourcePluginConfigurationsInNewTransaction(List<Integer> resourceIds,
ConfigurationDefinitionUpdateReport updateReport) {
ResourceCriteria criteria = new ResourceCriteria();
criteria.addFilterIds(resourceIds.toArray(new Integer[resourceIds.size()]));
criteria.setPageControl(PageControl.getUnlimitedInstance());
List<Resource> resources = resourceMgr.findResourcesByCriteria(subjectMgr.getOverlord(), criteria);
for (Resource resource : resources) {
boolean modified = false;
ConfigurationTemplate template = updateReport.getConfigurationDefinition().getDefaultTemplate();
Configuration templateConfiguration = template.getConfiguration();
for (PropertyDefinition propertyDef : updateReport.getNewPropertyDefinitions()) {
if (propertyDef.isRequired()) {
Property templateProperty = templateConfiguration.get(propertyDef.getName());
if (templateProperty == null) {
throw new IllegalArgumentException("The property [" + propertyDef.getName()
+ "] marked as required in the configuration definition of ["
+ propertyDef.getConfigurationDefinition().getName() + "] has no attribute 'default'");
} else {
// we only pull the configuration when an update is needed. The getProperties call
// just ensures the lazy load happens.
Configuration pluginConfiguration = resource.getPluginConfiguration();
int numberOfProperties = pluginConfiguration.getProperties().size();
pluginConfiguration.put(templateProperty.deepCopy(false));
modified = true;
}
}
}
for (PropertyDefinition propertyDef : updateReport.getUpdatedPropertyDefinitions()) {
if (propertyDef.isRequired()) {
// we only pull the configuration when an update is needed. The getProperties call
// just ensures the lazy load happens.
Configuration pluginConfiguration = resource.getPluginConfiguration();
int numberOfProperties = pluginConfiguration.getProperties().size();
String propertyValue = pluginConfiguration.getSimpleValue(propertyDef.getName(), null);
if (propertyValue == null) {
Property templateProperty = templateConfiguration.get(propertyDef.getName());
pluginConfiguration.put(templateProperty.deepCopy(false));
modified = true;
}
}
}
if (modified) {
resource.setAgentSynchronizationNeeded();
}
}
}
}