/* * JBoss, Home of Professional Open Source. * Copyright 2012, Red Hat, Inc., 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.test.integration.domain.extension; import org.jboss.as.controller.ExtensionContext; import org.jboss.as.controller.ModelVersion; import org.jboss.as.controller.OperationContext; import org.jboss.as.controller.OperationFailedException; import org.jboss.as.controller.OperationStepHandler; import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.PathElement; import org.jboss.as.controller.SubsystemRegistration; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.COMPOSITE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.NAME; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.READ_RESOURCE_OPERATION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESULT; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.STEPS; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.VALUE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.WRITE_ATTRIBUTE_OPERATION; import org.jboss.as.controller.parsing.ExtensionParsingContext; import org.jboss.as.controller.registry.ManagementResourceRegistration; import org.jboss.as.controller.registry.Resource; import org.jboss.as.controller.transform.OperationResultTransformer; import org.jboss.as.controller.transform.OperationTransformer; import org.jboss.as.controller.transform.RejectExpressionValuesTransformer; import org.jboss.as.controller.transform.ResourceTransformationContext; import org.jboss.as.controller.transform.ResourceTransformer; import org.jboss.as.controller.transform.TransformationContext; import org.jboss.as.controller.transform.description.RejectAttributeChecker; import org.jboss.as.controller.transform.description.ResourceTransformationDescriptionBuilder; import org.jboss.as.controller.transform.description.TransformationDescription; import org.jboss.as.controller.transform.description.TransformationDescriptionBuilder; import org.jboss.dmr.ModelNode; /** * Version 2 of an extension. * * @author Emanuel Muckenhuber */ public class VersionedExtension2 extends VersionedExtensionCommon { // New element which does not exist in v1 private static final PathElement NEW_ELEMENT = PathElement.pathElement("new-element"); // Other new element which does not exist in v1 private static final PathElement OTHER_NEW_ELEMENT = PathElement.pathElement("other-new-element"); // Element which is element>renamed in v2 private static final PathElement RENAMED = PathElement.pathElement("renamed", "element"); private static final SubsystemInitialization TEST_SUBSYSTEM = new SubsystemInitialization(SUBSYSTEM_NAME, true); private static final RejectExpressionValuesTransformer rejectExpressions = new RejectExpressionValuesTransformer("int", "string"); void processTestSubsystem(final SubsystemRegistration subsystem, final ManagementResourceRegistration registration) { // Register an update operation, which requires the transformer to create composite operation registration.registerOperationHandler(getOperationDefinition("update"), new OperationStepHandler() { @Override public void execute(final OperationContext context, final ModelNode operation) throws OperationFailedException { final Resource resource = context.readResourceForUpdate(PathAddress.EMPTY_ADDRESS); final ModelNode model = resource.getModel(); model.get("test-attribute").set("test"); context.getResult().set(model); } }); // Add a new model, which does not exist in the old model registration.registerSubModel(createResourceDefinition(NEW_ELEMENT)); registration.registerSubModel(createResourceDefinition(OTHER_NEW_ELEMENT)); // Add the renamed model registration.registerSubModel(createResourceDefinition(RENAMED)); registration.registerOperationHandler(getOperationDefinition("test"), new OperationStepHandler() { @Override public void execute(OperationContext context, ModelNode operation) throws OperationFailedException { context.getResult().set(true); } }); // // Transformation rules // final ResourceTransformationDescriptionBuilder subsystemBuilder = TransformationDescriptionBuilder.Factory.createSubsystemInstance(); subsystemBuilder.getAttributeBuilder() .addRejectCheck(RejectAttributeChecker.SIMPLE_EXPRESSIONS, "int", "string") .end() .addRawOperationTransformationOverride("update", new UpdateTransformer()) .addOperationTransformationOverride("test") .inheritResourceAttributeDefinitions() .setCustomOperationTransformer(new OperationTransformer() { @Override public TransformedOperation transformOperation(TransformationContext context, PathAddress address, ModelNode operation) throws OperationFailedException { return new TransformedOperation(operation, new OperationResultTransformer() { @Override public ModelNode transformResult(ModelNode result) { result.get(RESULT).set(false); return result; } }); } }) ; final ModelVersion version = ModelVersion.create(1, 0, 0); // Discard the operations to the new element subsystemBuilder.discardChildResource(NEW_ELEMENT); // Reject operations to the other new element subsystemBuilder.rejectChildResource(OTHER_NEW_ELEMENT); // Register an alias operation transformer, transforming renamed>element to element>renamed subsystemBuilder.addChildRedirection(RENAMED, PathElement.pathElement("element", "renamed")); // Register TransformationDescription.Tools.register(subsystemBuilder.build(), subsystem, version); } @Override public void initialize(final ExtensionContext context) { // Normal test subsystem final SubsystemInitialization.RegistrationResult result1 = TEST_SUBSYSTEM.initializeSubsystem(context, ModelVersion.create(2, 0, 0)); processTestSubsystem(result1.getSubsystemRegistration(), result1.getResourceRegistration()); } @Override public void initializeParsers(ExtensionParsingContext context) { TEST_SUBSYSTEM.initializeParsers(context); } static ResourceTransformer RESOURCE_TRANSFORMER = new ResourceTransformer() { @Override public void transformResource(ResourceTransformationContext context, PathAddress address, Resource resource) throws OperationFailedException { final ResourceTransformationContext childContext = context.addTransformedResource(PathAddress.EMPTY_ADDRESS, resource); for(final Resource.ResourceEntry entry : resource.getChildren("renamed")) { childContext.processChild(PathElement.pathElement("element", "renamed"), entry); } } }; static class UpdateTransformer implements OperationTransformer { @Override public TransformedOperation transformOperation(final TransformationContext context, final PathAddress address, final ModelNode operation) { // TODO does the operation transformer have to deal w/ profile in the address ? // final ModelNode addr = PathAddress.pathAddress(SUBSYSTEM_PATH).toModelNode(); final ModelNode addr = address.toModelNode(); final ModelNode write = new ModelNode(); write.get(OP).set(WRITE_ATTRIBUTE_OPERATION); write.get(OP_ADDR).set(addr); write.get(NAME).set(TEST_ATTRIBUTE.getName()); write.get(VALUE).set("test"); final ModelNode read = new ModelNode(); read.get(OP).set(READ_RESOURCE_OPERATION); read.get(OP_ADDR).set(addr); final ModelNode composite = new ModelNode(); composite.get(OP).set(COMPOSITE); composite.get(OP_ADDR).setEmptyList(); composite.get(STEPS).add(write); composite.get(STEPS).add(read); return new TransformedOperation(composite, new OperationResultTransformer() { @Override public ModelNode transformResult(final ModelNode result) { final ModelNode transformed = result.clone(); transformed.get(RESULT).set(result.get(RESULT, "step-2", RESULT)); return transformed; } }); } } }