/*
* JBoss, Home of Professional Open Source.
* Copyright 2011, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.logging;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import org.jboss.as.controller.AttributeDefinition;
import org.jboss.as.controller.ModelVersion;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.logging.logmanager.ConfigurationPersistence;
import org.jboss.as.model.test.FailedOperationTransformationConfig;
import org.jboss.as.model.test.FailedOperationTransformationConfig.NewAttributesConfig;
import org.jboss.as.model.test.FailedOperationTransformationConfig.RejectExpressionsConfig;
import org.jboss.as.model.test.ModelFixer;
import org.jboss.as.model.test.ModelTestControllerVersion;
import org.jboss.as.model.test.ModelTestUtils;
import org.jboss.as.subsystem.test.KernelServices;
import org.jboss.as.subsystem.test.KernelServicesBuilder;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;
import org.jboss.dmr.Property;
import org.jboss.logmanager.LogContext;
import org.junit.Assert;
import org.junit.Test;
import org.wildfly.security.manager.WildFlySecurityManager;
/**
* @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
* @author <a href="mailto:jperkins@redhat.com">James R. Perkins</a>
*/
public class LoggingSubsystemTestCase extends AbstractLoggingSubsystemTest {
@Override
protected String getSubsystemXml() throws IOException {
return readResource("/logging.xml");
}
@Override
protected String getSubsystemXsdPath() throws Exception {
return "schema/jboss-as-logging_3_0.xsd";
}
@Test
public void testExpressions() throws Exception {
standardSubsystemTest("/expressions.xml");
}
@Test
public void testConfiguration() throws Exception {
final KernelServices kernelServices = boot();
final ModelNode currentModel = getSubsystemModel(kernelServices);
compare(currentModel, ConfigurationPersistence.getConfigurationPersistence(LogContext.getLogContext()));
// Compare properties written out to current model
final String dir = resolveRelativePath(kernelServices, "jboss.server.config.dir");
Assert.assertNotNull("jboss.server.config.dir could not be resolved", dir);
final LogContext logContext = LogContext.create();
final ConfigurationPersistence config = ConfigurationPersistence.getOrCreateConfigurationPersistence(logContext);
final FileInputStream in = new FileInputStream(new File(dir, "logging.properties"));
config.configure(in);
compare(currentModel, config);
}
@Test
public void testLegacyConfigurations() throws Exception {
// Get a list of all the logging_x_x.xml files
final Pattern pattern = Pattern.compile("(logging|expressions)_\\d+_\\d+\\.xml");
// Using the CP as that's the standardSubsystemTest will use to find the config file
final String cp = WildFlySecurityManager.getPropertyPrivileged("java.class.path", ".");
final String[] entries = cp.split(Pattern.quote(File.pathSeparator));
final List<String> configs = new ArrayList<>();
for (String entry : entries) {
final Path path = Paths.get(entry);
if (Files.isDirectory(path)) {
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
final String name = file.getFileName().toString();
if (pattern.matcher(name).matches()) {
configs.add("/" + name);
}
return FileVisitResult.CONTINUE;
}
});
}
}
// The paths shouldn't be empty
Assert.assertFalse("No configs were found", configs.isEmpty());
for (String configId : configs) {
// Run the standard subsystem test, but don't compare the XML as it should never match
standardSubsystemTest(configId, false);
}
}
@Test
public void testTransformersEAP620() throws Exception {
testEapTransformer(ModelTestControllerVersion.EAP_6_2_0, ModelVersion.create(1, 3, 0), readResource("/logging_1_3.xml"),
AsyncModelFixer.INSTANCE,
// Using a ModelFixer to remove an attribute from the legacy model that the transformer removes seems odd here.
// However, the category attribute is a read-only attribute resolved at runtime by the name of the resource.
// WildFly does not require the ModelFixer as read-only attributes can be left off. If a change is made in EAP
// to do the same thing, this ModelFixer can and should be removed.
new AttributeRemovalModelFixer(LoggerResourceDefinition.CATEGORY));
}
@Test
public void testFailedTransformersEAP620() throws Exception {
final ModelTestControllerVersion controllerVersion = ModelTestControllerVersion.EAP_6_2_0;
final ModelVersion modelVersion = ModelVersion.create(1, 3, 0);
final PathAddress loggingProfileAddress = SUBSYSTEM_ADDRESS.append(CommonAttributes.LOGGING_PROFILE);
// Test against current
testEapFailedTransformers(controllerVersion, modelVersion, readResource("/expressions.xml"),
new FailedOperationTransformationConfig()
.addFailedAttribute(SUBSYSTEM_ADDRESS, new NewAttributesConfig(LoggingResourceDefinition.ADD_LOGGING_API_DEPENDENCIES, LoggingResourceDefinition.USE_DEPLOYMENT_LOGGING_CONFIG))
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(ConsoleHandlerResourceDefinition.CONSOLE_HANDLER_PATH),
new RejectExpressionsConfig(ConsoleHandlerResourceDefinition.TARGET))
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(FileHandlerResourceDefinition.FILE_HANDLER_PATH),
new NewAttributesConfig(FileHandlerResourceDefinition.NAMED_FORMATTER))
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(PatternFormatterResourceDefinition.PATTERN_FORMATTER_PATH),
FailedOperationTransformationConfig.REJECTED_RESOURCE)
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(PeriodicSizeRotatingHandlerResourceDefinition.PERIODIC_SIZE_ROTATING_HANDLER_PATH),
FailedOperationTransformationConfig.REJECTED_RESOURCE)
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(SizeRotatingHandlerResourceDefinition.SIZE_ROTATING_HANDLER_PATH),
new FailedOperationTransformationConfig.NewAttributesConfig(SizeRotatingHandlerResourceDefinition.SUFFIX))
.addFailedAttribute(loggingProfileAddress.append(ConsoleHandlerResourceDefinition.CONSOLE_HANDLER_PATH),
new RejectExpressionsConfig(ConsoleHandlerResourceDefinition.TARGET))
.addFailedAttribute(loggingProfileAddress.append(FileHandlerResourceDefinition.FILE_HANDLER_PATH),
new NewAttributesConfig(FileHandlerResourceDefinition.NAMED_FORMATTER))
.addFailedAttribute(loggingProfileAddress.append(PatternFormatterResourceDefinition.PATTERN_FORMATTER_PATH),
FailedOperationTransformationConfig.REJECTED_RESOURCE)
.addFailedAttribute(loggingProfileAddress.append(PeriodicSizeRotatingHandlerResourceDefinition.PERIODIC_SIZE_ROTATING_HANDLER_PATH),
FailedOperationTransformationConfig.REJECTED_RESOURCE)
.addFailedAttribute(loggingProfileAddress.append(SizeRotatingHandlerResourceDefinition.SIZE_ROTATING_HANDLER_PATH),
new FailedOperationTransformationConfig.NewAttributesConfig(SizeRotatingHandlerResourceDefinition.SUFFIX)));
}
@Test
public void testTransformersEAP630() throws Exception {
testEapTransformer(ModelTestControllerVersion.EAP_6_3_0, ModelVersion.create(1, 4, 0), readResource("/logging_1_4.xml"),
AsyncModelFixer.INSTANCE,
// In WildFly Core the default formatter changed from %E (extended exceptions) to %e. When the legacy
// model is compared to the new model and the formatter is not defined or a named-formatter is used the
// check fails due to the formatter difference. This is not ideal, but will work as the difference isn't
// important.
new AttributeValueChangerModelFixer(AbstractHandlerDefinition.FORMATTER, "%E", "%e")
);
}
@Test
public void testFailedTransformersEAP630() throws Exception {
final ModelTestControllerVersion controllerVersion = ModelTestControllerVersion.EAP_6_3_0;
final ModelVersion modelVersion = ModelVersion.create(1, 4, 0);
final PathAddress loggingProfileAddress = SUBSYSTEM_ADDRESS.append(CommonAttributes.LOGGING_PROFILE);
// Test against current
testEapFailedTransformers(controllerVersion, modelVersion, readResource("/expressions.xml"),
new FailedOperationTransformationConfig()
.addFailedAttribute(SUBSYSTEM_ADDRESS, new NewAttributesConfig(LoggingResourceDefinition.USE_DEPLOYMENT_LOGGING_CONFIG))
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(ConsoleHandlerResourceDefinition.CONSOLE_HANDLER_PATH),
new RejectExpressionsConfig(ConsoleHandlerResourceDefinition.TARGET))
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(PeriodicSizeRotatingHandlerResourceDefinition.PERIODIC_SIZE_ROTATING_HANDLER_PATH),
FailedOperationTransformationConfig.REJECTED_RESOURCE)
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(SizeRotatingHandlerResourceDefinition.SIZE_ROTATING_HANDLER_PATH),
new FailedOperationTransformationConfig.NewAttributesConfig(SizeRotatingHandlerResourceDefinition.SUFFIX))
.addFailedAttribute(loggingProfileAddress.append(ConsoleHandlerResourceDefinition.CONSOLE_HANDLER_PATH),
new RejectExpressionsConfig(ConsoleHandlerResourceDefinition.TARGET))
.addFailedAttribute(loggingProfileAddress.append(PeriodicSizeRotatingHandlerResourceDefinition.PERIODIC_SIZE_ROTATING_HANDLER_PATH),
FailedOperationTransformationConfig.REJECTED_RESOURCE)
.addFailedAttribute(loggingProfileAddress.append(SizeRotatingHandlerResourceDefinition.SIZE_ROTATING_HANDLER_PATH),
new FailedOperationTransformationConfig.NewAttributesConfig(SizeRotatingHandlerResourceDefinition.SUFFIX)));
}
@Test
public void testTransformersEAP640() throws Exception {
testEapTransformer(ModelTestControllerVersion.EAP_6_4_0, ModelVersion.create(1, 5, 0), readResource("/logging_1_5.xml"),
AsyncModelFixer.INSTANCE,
// In WildFly Core the default formatter changed from %E (extended exceptions) to %e. When the legacy
// model is compared to the new model and the formatter is not defined or a named-formatter is used the
// check fails due to the formatter difference. This is not ideal, but will work as the difference isn't
// important.
new AttributeValueChangerModelFixer(AbstractHandlerDefinition.FORMATTER, "%E", "%e")
);
}
@Test
public void testFailedTransformersEAP640() throws Exception {
final ModelTestControllerVersion controllerVersion = ModelTestControllerVersion.EAP_6_4_0;
final ModelVersion modelVersion = ModelVersion.create(1, 5, 0);
final PathAddress loggingProfileAddress = SUBSYSTEM_ADDRESS.append(CommonAttributes.LOGGING_PROFILE);
// Test against current
testEapFailedTransformers(controllerVersion, modelVersion, readResource("/expressions.xml"),
new FailedOperationTransformationConfig()
.addFailedAttribute(SUBSYSTEM_ADDRESS, new NewAttributesConfig(LoggingResourceDefinition.USE_DEPLOYMENT_LOGGING_CONFIG))
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(ConsoleHandlerResourceDefinition.CONSOLE_HANDLER_PATH),
new RejectExpressionsConfig(ConsoleHandlerResourceDefinition.TARGET))
.addFailedAttribute(loggingProfileAddress.append(ConsoleHandlerResourceDefinition.CONSOLE_HANDLER_PATH),
new RejectExpressionsConfig(ConsoleHandlerResourceDefinition.TARGET)));
}
@Test
public void testTransformersWildFly800() throws Exception {
testWildFlyTransformer(ModelTestControllerVersion.WILDFLY_8_0_0_FINAL, ModelVersion.create(2, 0, 0), readResource("/logging_2_0.xml"),
// In WildFly Core the default formatter changed from %E (extended exceptions) to %e. When the legacy
// model is compared to the new model and the formatter is not defined or a named-formatter is used the
// check fails due to the formatter difference. This is not ideal, but will work as the difference isn't
// important.
new AttributeValueChangerModelFixer(AbstractHandlerDefinition.FORMATTER, "%E", "%e")
);
}
@Test
public void testFailedTransformersWildFly800() throws Exception {
final ModelTestControllerVersion controllerVersion = ModelTestControllerVersion.WILDFLY_8_0_0_FINAL;
final ModelVersion modelVersion = ModelVersion.create(2, 0, 0);
final PathAddress loggingProfileAddress = SUBSYSTEM_ADDRESS.append(CommonAttributes.LOGGING_PROFILE);
// Test against current
testWildFlyFailedTransformers(controllerVersion, modelVersion, readResource("/expressions.xml"),
new FailedOperationTransformationConfig()
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(ConsoleHandlerResourceDefinition.CONSOLE_HANDLER_PATH),
new RejectExpressionsConfig(ConsoleHandlerResourceDefinition.TARGET))
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(PeriodicSizeRotatingHandlerResourceDefinition.PERIODIC_SIZE_ROTATING_HANDLER_PATH),
FailedOperationTransformationConfig.REJECTED_RESOURCE)
.addFailedAttribute(SUBSYSTEM_ADDRESS.append(SizeRotatingHandlerResourceDefinition.SIZE_ROTATING_HANDLER_PATH),
new FailedOperationTransformationConfig.NewAttributesConfig(SizeRotatingHandlerResourceDefinition.SUFFIX))
.addFailedAttribute(loggingProfileAddress.append(ConsoleHandlerResourceDefinition.CONSOLE_HANDLER_PATH),
new RejectExpressionsConfig(ConsoleHandlerResourceDefinition.TARGET))
.addFailedAttribute(loggingProfileAddress.append(PeriodicSizeRotatingHandlerResourceDefinition.PERIODIC_SIZE_ROTATING_HANDLER_PATH),
FailedOperationTransformationConfig.REJECTED_RESOURCE)
.addFailedAttribute(loggingProfileAddress.append(SizeRotatingHandlerResourceDefinition.SIZE_ROTATING_HANDLER_PATH),
new FailedOperationTransformationConfig.NewAttributesConfig(SizeRotatingHandlerResourceDefinition.SUFFIX)));
}
@Test
public void testTransformersEAP700() throws Exception {
testEap7Transformer(ModelTestControllerVersion.EAP_7_0_0, ModelVersion.create(3, 0, 0), readResource("/logging_3_0.xml") );
}
private void testEap7Transformer(final ModelTestControllerVersion controllerVersion, final ModelVersion legacyModelVersion, final String subsystemXml, final ModelFixer... modelFixers) throws Exception {
final KernelServicesBuilder builder = createKernelServicesBuilder(LoggingTestEnvironment.getManagementInstance())
.setSubsystemXml(subsystemXml);
// Create the legacy kernel
builder.createLegacyKernelServicesBuilder(LoggingTestEnvironment.getManagementInstance(), controllerVersion, legacyModelVersion)
.addMavenResourceURL(controllerVersion.getCoreMavenGroupId() + ":wildfly-logging:" + controllerVersion.getCoreVersion())
.dontPersistXml()
.addSingleChildFirstClass(LoggingTestEnvironment.class, LoggingTestEnvironment.LoggingInitializer.class)
.configureReverseControllerCheck(LoggingTestEnvironment.getManagementInstance(), null);
KernelServices mainServices = builder.build();
Assert.assertTrue(mainServices.isSuccessfulBoot());
KernelServices legacyServices = mainServices.getLegacyServices(legacyModelVersion);
Assert.assertTrue(legacyServices.isSuccessfulBoot());
Assert.assertNotNull(legacyServices);
checkSubsystemModelTransformation(mainServices, legacyModelVersion, new ChainedModelFixer(modelFixers));
}
private void testEapTransformer(final ModelTestControllerVersion controllerVersion, final ModelVersion legacyModelVersion, final String subsystemXml, final ModelFixer... modelFixers) throws Exception {
final KernelServicesBuilder builder = createKernelServicesBuilder(LoggingTestEnvironment.getManagementInstance())
.setSubsystemXml(subsystemXml);
// Create the legacy kernel
builder.createLegacyKernelServicesBuilder(LoggingTestEnvironment.getManagementInstance(), controllerVersion, legacyModelVersion)
.addMavenResourceURL("org.jboss.as:jboss-as-logging:" + controllerVersion.getMavenGavVersion())
.dontPersistXml()
.addSingleChildFirstClass(LoggingTestEnvironment.class, LoggingTestEnvironment.LoggingInitializer.class)
.configureReverseControllerCheck(LoggingTestEnvironment.getManagementInstance(), null);
KernelServices mainServices = builder.build();
Assert.assertTrue(mainServices.isSuccessfulBoot());
KernelServices legacyServices = mainServices.getLegacyServices(legacyModelVersion);
Assert.assertTrue(legacyServices.isSuccessfulBoot());
Assert.assertNotNull(legacyServices);
checkSubsystemModelTransformation(mainServices, legacyModelVersion, new ChainedModelFixer(modelFixers));
}
private void testEapFailedTransformers(final ModelTestControllerVersion controllerVersion, final ModelVersion legacyModelVersion, final String subsystemXml, final FailedOperationTransformationConfig config) throws Exception {
final KernelServicesBuilder builder = createKernelServicesBuilder(LoggingTestEnvironment.getManagementInstance());
// Create the legacy kernel
builder.createLegacyKernelServicesBuilder(LoggingTestEnvironment.getManagementInstance(), controllerVersion, legacyModelVersion)
.addMavenResourceURL("org.jboss.as:jboss-as-logging:" + controllerVersion.getMavenGavVersion())
.dontPersistXml()
.addSingleChildFirstClass(LoggingTestEnvironment.class, LoggingTestEnvironment.LoggingInitializer.class)
.configureReverseControllerCheck(LoggingTestEnvironment.getManagementInstance(), null);
KernelServices mainServices = builder.build();
KernelServices legacyServices = mainServices.getLegacyServices(legacyModelVersion);
Assert.assertNotNull(legacyServices);
Assert.assertTrue("main services did not boot", mainServices.isSuccessfulBoot());
Assert.assertTrue(legacyServices.isSuccessfulBoot());
final List<ModelNode> ops = builder.parseXml(subsystemXml);
ModelTestUtils.checkFailedTransformedBootOperations(mainServices, legacyModelVersion, ops, config);
}
private void testWildFlyTransformer(final ModelTestControllerVersion controllerVersion, final ModelVersion legacyModelVersion, final String subsystemXml, final ModelFixer... modelFixers) throws Exception {
final KernelServicesBuilder builder = createKernelServicesBuilder(LoggingTestEnvironment.getManagementInstance())
.setSubsystemXml(subsystemXml);
// Create the legacy kernel
builder.createLegacyKernelServicesBuilder(LoggingTestEnvironment.getManagementInstance(), controllerVersion, legacyModelVersion)
.addMavenResourceURL("org.wildfly:wildfly-logging:" + controllerVersion.getMavenGavVersion())
.dontPersistXml()
.addSingleChildFirstClass(LoggingTestEnvironment.class, LoggingTestEnvironment.LoggingInitializer.class)
.configureReverseControllerCheck(LoggingTestEnvironment.getManagementInstance(), null);
KernelServices mainServices = builder.build();
Assert.assertTrue(mainServices.isSuccessfulBoot());
KernelServices legacyServices = mainServices.getLegacyServices(legacyModelVersion);
Assert.assertTrue(legacyServices.isSuccessfulBoot());
Assert.assertNotNull(legacyServices);
checkSubsystemModelTransformation(mainServices, legacyModelVersion, new ChainedModelFixer(modelFixers));
}
private void testWildFlyFailedTransformers(final ModelTestControllerVersion controllerVersion, final ModelVersion legacyModelVersion, final String subsystemXml, final FailedOperationTransformationConfig config) throws Exception {
final KernelServicesBuilder builder = createKernelServicesBuilder(LoggingTestEnvironment.getManagementInstance());
// Create the legacy kernel
builder.createLegacyKernelServicesBuilder(LoggingTestEnvironment.getManagementInstance(), controllerVersion, legacyModelVersion)
.addMavenResourceURL("org.wildfly:wildfly-logging:" + controllerVersion.getMavenGavVersion())
.dontPersistXml()
.addSingleChildFirstClass(LoggingTestEnvironment.class, LoggingTestEnvironment.LoggingInitializer.class)
.configureReverseControllerCheck(LoggingTestEnvironment.getManagementInstance(), null);
KernelServices mainServices = builder.build();
KernelServices legacyServices = mainServices.getLegacyServices(legacyModelVersion);
Assert.assertNotNull(legacyServices);
Assert.assertTrue("main services did not boot", mainServices.isSuccessfulBoot());
Assert.assertTrue(legacyServices.isSuccessfulBoot());
final List<ModelNode> ops = builder.parseXml(subsystemXml);
ModelTestUtils.checkFailedTransformedBootOperations(mainServices, legacyModelVersion, ops, config);
}
private static class ChainedModelFixer implements ModelFixer {
private final ModelFixer[] modelFixers;
private ChainedModelFixer(final ModelFixer... modelFixers) {
this.modelFixers = modelFixers;
}
@Override
public ModelNode fixModel(final ModelNode modelNode) {
ModelNode result = modelNode;
for (ModelFixer modelFixer : modelFixers) {
result = modelFixer.fixModel(result);
}
return result;
}
}
private static class AsyncModelFixer implements ModelFixer {
static final AsyncModelFixer INSTANCE = new AsyncModelFixer();
@Override
public ModelNode fixModel(final ModelNode modelNode) {
// Find the async-handler
if (modelNode.hasDefined(AsyncHandlerResourceDefinition.ASYNC_HANDLER)) {
final ModelNode asyncHandlers = modelNode.get(AsyncHandlerResourceDefinition.ASYNC_HANDLER);
for (Property asyncHandler : asyncHandlers.asPropertyList()) {
final ModelNode async = asyncHandler.getValue();
async.remove(CommonAttributes.ENCODING.getName());
async.remove(AbstractHandlerDefinition.FORMATTER.getName());
asyncHandlers.get(asyncHandler.getName()).set(async);
}
}
return modelNode;
}
}
private static class AttributeRemovalModelFixer implements ModelFixer {
private final AttributeDefinition[] attributes;
AttributeRemovalModelFixer(final AttributeDefinition... attributes) {
this.attributes = attributes;
}
@Override
public ModelNode fixModel(final ModelNode modelNode) {
// Recursively remove the attributes
if (modelNode.getType() == ModelType.OBJECT) {
for (Property property : modelNode.asPropertyList()) {
final String name = property.getName();
final ModelNode value = property.getValue();
if (value.isDefined()) {
if (value.getType() == ModelType.OBJECT) {
modelNode.get(name).set(fixModel(value));
} else {
for (AttributeDefinition attribute : attributes) {
if (name.equals(attribute.getName())) {
modelNode.remove(name);
}
}
}
}
}
}
return modelNode;
}
}
private static class AttributeValueChangerModelFixer implements ModelFixer {
private final AttributeDefinition attribute;
private final String from;
private final String to;
private AttributeValueChangerModelFixer(final AttributeDefinition attribute, final String from, final String to) {
this.attribute = attribute;
this.from = from;
this.to = to;
}
@Override
public ModelNode fixModel(final ModelNode modelNode) {
// Recursively remove the attributes
if (modelNode.getType() == ModelType.OBJECT) {
for (Property property : modelNode.asPropertyList()) {
final String name = property.getName();
final ModelNode value = property.getValue();
if (value.isDefined()) {
if (value.getType() == ModelType.OBJECT) {
modelNode.get(name).set(fixModel(value));
} else if (value.getType() == ModelType.STRING) {
if (name.equals(attribute.getName())) {
modelNode.get(name).set(value.asString().replace(from, to));
}
}
}
}
}
return modelNode;
}
}
}