/*
* RHQ Management Platform
* Copyright (C) 2005-2014 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.modules.plugins.wildfly10;
import static org.rhq.core.domain.configuration.ConfigurationUpdateStatus.FAILURE;
import static org.rhq.core.util.StringUtil.isNotBlank;
import java.util.ArrayList;
import java.util.List;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.Property;
import org.rhq.core.domain.configuration.PropertyList;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
import org.rhq.modules.plugins.wildfly10.json.Address;
import org.rhq.modules.plugins.wildfly10.json.CompositeOperation;
import org.rhq.modules.plugins.wildfly10.json.Operation;
import org.rhq.modules.plugins.wildfly10.json.Result;
import org.rhq.modules.plugins.wildfly10.json.UndefineAttribute;
import org.rhq.modules.plugins.wildfly10.json.WriteAttribute;
/**
* Resource backed by this component must define either a discovery group name <strong>or</strong> a connector. Resource
* configuration update must happen in two steps:
* <ol>
* <li>execute a composite operation to set one of these two attributes and unset the other one</li>
* <li>use the standard {@link ConfigurationWriteDelegate} for all other attributes</li>
* </ol>
*
* @author Stefan Negrea
*/
public class ConnectorDiscoveryGroupValidatorComponent extends BaseComponent<ResourceComponent<?>> {
private static final String DISCOVERY_GROUP_NAME = "discovery-group";
@Override
public void updateResourceConfiguration(ConfigurationUpdateReport report) {
ResourceType resourceType = context.getResourceType();
String resourceTypeName = resourceType.getName();
resourceTypeName = BaseComponent.resourceTypeNameByRemovingProfileSuffix(resourceTypeName);
ConfigurationUpdateHelper configurationUpdateHelper;
if (resourceTypeName.equals("Connection Factory") || resourceTypeName.equals("Pooled Connection Factory")) {
configurationUpdateHelper = new ConnectionFactoriesConfigurationUpdateHelper(getAddress(),
report.getConfiguration());
} else if (resourceTypeName.equals("Bridge") || resourceTypeName.equals("Cluster Connection")) {
configurationUpdateHelper = new DefaultConfigurationUpdateHelper(address, report.getConfiguration());
} else {
report.setStatus(FAILURE);
report.setErrorMessage(resourceType + " not supported");
return;
}
if (!configurationUpdateHelper.isConnectorXorDiscoveryGroupNameConfigured()) {
report.setStatus(FAILURE);
report.setErrorMessage(configurationUpdateHelper.getErrorMessage());
} else {
// First update the connector and discovery group name attributes in a batch
Operation batchOperation = configurationUpdateHelper.getBatchOperation();
Result result = getASConnection().execute(batchOperation);
if (!result.isSuccess()) {
report.setStatus(FAILURE);
report.setErrorMessage(result.getFailureDescription());
return;
}
// Now update the rest of the configuration attributes
ConfigurationDefinition configDefCopy = resourceType.getResourceConfigurationDefinition().copy();
configDefCopy.getPropertyDefinitions().remove(DISCOVERY_GROUP_NAME);
configDefCopy.getPropertyDefinitions().remove(configurationUpdateHelper.getConnectorPropertyName());
ConfigurationWriteDelegate delegate = new ConfigurationWriteDelegate(configDefCopy, getASConnection(),
address);
delegate.updateResourceConfiguration(report);
}
}
private static abstract class ConfigurationUpdateHelper {
final Configuration configuration;
final boolean hasDiscoveryGroupName;
final boolean hasConnector;
final boolean hasNoneOfTheAlternatives;
final String errorMessage;
ConfigurationUpdateHelper(Configuration configuration) {
this.configuration = configuration;
hasDiscoveryGroupName = isNotBlank(this.configuration.getSimpleValue(DISCOVERY_GROUP_NAME));
hasConnector = isConnectorPropertyDefined();
hasNoneOfTheAlternatives = hasDiscoveryGroupName == hasConnector && hasConnector == false;
errorMessage = getBeginningOfErrorMessage()
+ (hasNoneOfTheAlternatives ? " You provided none." : " You provided both.");
}
abstract String getConnectorPropertyName();
abstract boolean isConnectorPropertyDefined();
abstract String getBeginningOfErrorMessage();
boolean isConnectorXorDiscoveryGroupNameConfigured() {
return hasDiscoveryGroupName != hasConnector;
}
String getErrorMessage() {
return errorMessage;
}
public abstract Operation getBatchOperation();
boolean hasDiscoveryGroupName() {
return hasDiscoveryGroupName;
}
}
private static class ConnectionFactoriesConfigurationUpdateHelper extends ConfigurationUpdateHelper {
static final String CONNECTOR_ATTRIBUTE = "connectors";
static final String CONNECTOR_PROPERTY = CONNECTOR_ATTRIBUTE;
Address address;
ConnectionFactoriesConfigurationUpdateHelper(Address address, Configuration configuration) {
super(configuration);
this.address = address;
}
@Override
String getConnectorPropertyName() {
return CONNECTOR_PROPERTY;
}
@Override
boolean isConnectorPropertyDefined() {
PropertyList connector = configuration.getList(CONNECTOR_PROPERTY);
if (connector != null && connector.getList().size() > 0) {
Property property = connector.getList().get(0);
if (property instanceof PropertySimple) {
PropertySimple propertySimple = (PropertySimple) property;
return isNotBlank(propertySimple.getStringValue());
}
}
return false;
}
@Override
String getBeginningOfErrorMessage() {
return "You need to provide either a " + CONNECTOR_ATTRIBUTE + " name OR a discovery-group-name.";
}
@Override
public Operation getBatchOperation() {
CompositeOperation compositeOperation = new CompositeOperation();
if (hasDiscoveryGroupName()) {
compositeOperation.addStep(new UndefineAttribute(address, CONNECTOR_ATTRIBUTE));
compositeOperation.addStep(new WriteAttribute(address, DISCOVERY_GROUP_NAME, configuration
.getSimpleValue(DISCOVERY_GROUP_NAME)));
} else {
compositeOperation.addStep(new UndefineAttribute(address, DISCOVERY_GROUP_NAME));
List<Property> propertyList = configuration.getList(CONNECTOR_PROPERTY).getList();
List<String> connectors = new ArrayList<String>(propertyList.size());
for (Property property : propertyList) {
if (property instanceof PropertySimple) {
PropertySimple propertySimple = (PropertySimple) property;
connectors.add(propertySimple.getStringValue());
} else {
throw new IllegalArgumentException(property.getName() + " property has unexpected type: " + property.getClass());
}
}
compositeOperation.addStep(new WriteAttribute(address, CONNECTOR_PROPERTY, connectors));
}
return compositeOperation;
}
}
private static class DefaultConfigurationUpdateHelper extends ConfigurationUpdateHelper {
static final String STATIC_CONNECTORS_ATTRIBUTE = "static-connectors";
static final String STATIC_CONNECTORS_PROPERTY = STATIC_CONNECTORS_ATTRIBUTE + ":nullable";
final Address address;
public DefaultConfigurationUpdateHelper(Address address, Configuration configuration) {
super(configuration);
this.address = address;
}
@Override
String getConnectorPropertyName() {
return STATIC_CONNECTORS_PROPERTY;
}
@Override
boolean isConnectorPropertyDefined() {
PropertyList staticConnectors = configuration.getList(STATIC_CONNECTORS_PROPERTY);
return staticConnectors != null && !staticConnectors.getList().isEmpty();
}
@Override
String getBeginningOfErrorMessage() {
return "You need to provide either static connectors name OR a discovery-group-name.";
}
@Override
public Operation getBatchOperation() {
CompositeOperation compositeOperation = new CompositeOperation();
if (hasDiscoveryGroupName()) {
compositeOperation.addStep(new UndefineAttribute(address, STATIC_CONNECTORS_ATTRIBUTE));
compositeOperation.addStep(new WriteAttribute(address, DISCOVERY_GROUP_NAME, configuration
.getSimpleValue(DISCOVERY_GROUP_NAME)));
} else {
compositeOperation.addStep(new UndefineAttribute(address, DISCOVERY_GROUP_NAME));
List<Property> propertyList = configuration.getList(STATIC_CONNECTORS_PROPERTY).getList();
List<String> staticConnectors = new ArrayList<String>(propertyList.size());
for (Property property : propertyList) {
if (property instanceof PropertySimple) {
PropertySimple propertySimple = (PropertySimple) property;
staticConnectors.add(propertySimple.getStringValue());
} else {
getLog().warn(property.getName() + " property has unexpected type: " + property.getClass());
}
}
compositeOperation.addStep(new WriteAttribute(address, STATIC_CONNECTORS_ATTRIBUTE, staticConnectors));
}
return compositeOperation;
}
}
}