/*
* RHQ Management Platform
* Copyright (C) 2011 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.enterprise.server.drift;
import static javax.ejb.TransactionAttributeType.NEVER;
import static org.rhq.core.domain.common.EntityContext.forResource;
import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
import static org.rhq.core.domain.drift.DriftConfigurationDefinition.DriftHandlingMode.normal;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.criteria.DriftDefinitionCriteria;
import org.rhq.core.domain.criteria.DriftDefinitionTemplateCriteria;
import org.rhq.core.domain.drift.DriftDefinition;
import org.rhq.core.domain.drift.DriftDefinitionComparator;
import org.rhq.core.domain.drift.DriftDefinitionTemplate;
import org.rhq.core.domain.drift.DriftSnapshot;
import org.rhq.core.domain.drift.DriftSnapshotRequest;
import org.rhq.core.domain.drift.dto.DriftChangeSetDTO;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.authz.RequiredPermission;
import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
import org.rhq.enterprise.server.resource.ResourceTypeNotFoundException;
import org.rhq.enterprise.server.util.CriteriaQuery;
import org.rhq.enterprise.server.util.CriteriaQueryExecutor;
import org.rhq.enterprise.server.util.CriteriaQueryGenerator;
import org.rhq.enterprise.server.util.CriteriaQueryRunner;
@Stateless
public class DriftTemplateManagerBean implements DriftTemplateManagerLocal, DriftTemplateManagerRemote {
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
private EntityManager entityMgr;
@EJB
ResourceTypeManagerLocal resourceTypeMgr;
@EJB
DriftManagerLocal driftMgr;
@EJB
DriftTemplateManagerLocal templateMgr;
@Override
public PageList<DriftDefinitionTemplate> findTemplatesByCriteria(Subject subject,
DriftDefinitionTemplateCriteria criteria) {
CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
CriteriaQueryRunner<DriftDefinitionTemplate> queryRunner = new CriteriaQueryRunner<DriftDefinitionTemplate>(
criteria, generator, entityMgr);
PageList<DriftDefinitionTemplate> result = queryRunner.execute();
return result;
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
@Override
public DriftDefinitionTemplate createTemplate(Subject subject, int resourceTypeId, boolean isUserDefined,
DriftDefinition definition) {
try {
// before we do anything, validate certain field values to prevent downstream errors
if (isUserDefined) {
DriftManagerBean.validateDriftDefinition(definition);
}
ResourceType resourceType = resourceTypeMgr.getResourceTypeById(subject, resourceTypeId);
DriftDefinitionTemplate template = new DriftDefinitionTemplate();
template.setName(definition.getName());
template.setDescription(definition.getDescription());
template.setUserDefined(isUserDefined);
template.setTemplateDefinition(definition);
if (isDuplicateName(resourceType, template)) {
throw new IllegalArgumentException("Drift definition template name must be unique. A template named "
+ "[" + template.getName() + "] already exists for " + resourceType);
}
resourceType.addDriftDefinitionTemplate(template);
entityMgr.persist(template);
return template;
} catch (ResourceTypeNotFoundException e) {
throw new RuntimeException("Failed to create template", e);
}
}
private boolean isDuplicateName(ResourceType resourceType, DriftDefinitionTemplate newTemplate) {
for (DriftDefinitionTemplate template : resourceType.getDriftDefinitionTemplates()) {
if (template.getName().equals(newTemplate.getName())) {
return true;
}
}
return false;
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
@Override
@TransactionAttribute(NEVER)
public void pinTemplate(final Subject subject, int templateId, int driftDefId, int snapshotVersion) {
templateMgr.createTemplateChangeSet(subject, templateId, driftDefId, snapshotVersion);
DriftDefinitionTemplateCriteria templateCriteria = new DriftDefinitionTemplateCriteria();
templateCriteria.addFilterId(templateId);
templateCriteria.fetchDriftDefinitions(true);
templateCriteria.setPageControl(PageControl.getSingleRowInstance());
PageList<DriftDefinitionTemplate> templates = templateMgr.findTemplatesByCriteria(subject, templateCriteria);
DriftDefinitionTemplate template = templates.get(0);
DriftDefinitionCriteria criteria = new DriftDefinitionCriteria();
criteria.addFilterTemplateId(templateId);
criteria.fetchConfiguration(true);
criteria.fetchResource(true);
//Use CriteriaQuery to automatically chunk/page through criteria query results
CriteriaQueryExecutor<DriftDefinition, DriftDefinitionCriteria> queryExecutor = new CriteriaQueryExecutor<DriftDefinition, DriftDefinitionCriteria>() {
@Override
public PageList<DriftDefinition> execute(DriftDefinitionCriteria criteria) {
return driftMgr.findDriftDefinitionsByCriteria(subject, criteria);
}
};
CriteriaQuery<DriftDefinition, DriftDefinitionCriteria> definitions = new CriteriaQuery<DriftDefinition, DriftDefinitionCriteria>(
criteria, queryExecutor);
for (DriftDefinition def : definitions) {
if (def.isAttached()) {
int resourceId = def.getResource().getId();
driftMgr.deleteDriftDefinition(subject, forResource(resourceId), def.getName());
DriftDefinition newDef = new DriftDefinition(def.getConfiguration().deepCopyWithoutProxies());
newDef.setTemplate(template);
newDef.setPinned(true);
driftMgr.updateDriftDefinition(subject, forResource(resourceId), newDef);
}
}
}
@Override
@TransactionAttribute
public void createTemplateChangeSet(Subject subject, int templateId, int driftDefId, int snapshotVersion) {
DriftDefinitionTemplate template = entityMgr.find(DriftDefinitionTemplate.class, templateId);
DriftSnapshot snapshot = driftMgr.getSnapshot(subject, new DriftSnapshotRequest(driftDefId, snapshotVersion));
DriftChangeSetDTO changeSetDTO = new DriftChangeSetDTO();
changeSetDTO.setCategory(COVERAGE);
changeSetDTO.setDriftHandlingMode(normal);
changeSetDTO.setVersion(0);
String newChangeSetId = driftMgr.persistSnapshot(subject, snapshot, changeSetDTO);
template.setChangeSetId(newChangeSetId);
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
@Override
public void deleteTemplate(Subject subject, int templateId) {
DriftDefinitionTemplate template = entityMgr.find(DriftDefinitionTemplate.class, templateId);
if (!template.isUserDefined()) {
throw new IllegalArgumentException(template.getName() + " is a plugin defined template. Plugin defined " +
"templates cannot be deleted.");
}
for (DriftDefinition defintion : template.getDriftDefinitions()) {
if (defintion.isAttached()) {
driftMgr.deleteDriftDefinition(subject, forResource(defintion.getResource().getId()), defintion
.getName());
} else {
defintion.setTemplate(null);
}
}
entityMgr.remove(template);
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
@Override
public void updateTemplate(Subject subject, DriftDefinitionTemplate updatedTemplate) {
DriftDefinitionTemplate template = entityMgr.find(DriftDefinitionTemplate.class, updatedTemplate.getId());
if (null == template) {
throw new IllegalArgumentException("Template with id [" + updatedTemplate.getId() + "] not found");
}
if (!template.isUserDefined()) {
throw new IllegalArgumentException("Plugin-defined templates cannot be be modified");
}
if (!template.getName().equals(updatedTemplate.getName())) {
throw new IllegalArgumentException("The template's name cannot be modified");
}
DriftDefinitionComparator comparator = new DriftDefinitionComparator(
DriftDefinitionComparator.CompareMode.ONLY_DIRECTORY_SPECIFICATIONS);
if (comparator.compare(template.getTemplateDefinition(), updatedTemplate.getTemplateDefinition()) != 0) {
throw new IllegalArgumentException("The template's base directory and filters cannot be modified");
}
entityMgr.remove(template.getTemplateDefinition());
template.setTemplateDefinition(updatedTemplate.getTemplateDefinition());
template = entityMgr.merge(template);
DriftDefinition templateDef = template.getTemplateDefinition();
for (DriftDefinition resourceDef : template.getDriftDefinitions()) {
DriftDefinition driftDef = entityMgr.find(DriftDefinition.class, resourceDef.getId());
if (driftDef.isAttached()) {
driftDef.setInterval(templateDef.getInterval());
driftDef.setDriftHandlingMode(templateDef.getDriftHandlingMode());
driftDef.setEnabled(templateDef.isEnabled());
driftMgr.updateDriftDefinition(subject, forResource(driftDef.getResource().getId()), driftDef);
}
}
}
}