/* * JBoss, Home of Professional Open Source. * Copyright 2013, 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.controller.transform.description; 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.UNDEFINE_ATTRIBUTE_OPERATION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.VALUE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.WRITE_ATTRIBUTE_OPERATION; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.jboss.as.controller.ExpressionResolver; import org.jboss.as.controller.ModelVersion; import org.jboss.as.controller.OperationFailedException; import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.PathElement; import org.jboss.as.controller.ProcessType; import org.jboss.as.controller.ResourceDefinition; import org.jboss.as.controller.RunningMode; import org.jboss.as.controller.SimpleResourceDefinition; import org.jboss.as.controller.descriptions.ModelDescriptionConstants; import org.jboss.as.controller.descriptions.NonResolvingResourceDescriptionResolver; import org.jboss.as.controller.operations.common.Util; import org.jboss.as.controller.registry.ManagementResourceRegistration; import org.jboss.as.controller.registry.Resource; import org.jboss.as.controller.transform.OperationTransformer; 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.TransformationTarget; import org.jboss.as.controller.transform.TransformationTargetImpl; import org.jboss.as.controller.transform.TransformerRegistry; import org.jboss.as.controller.transform.Transformers; import org.jboss.as.controller.transform.TransformersSubRegistration; import org.jboss.as.controller.transform.description.AttributeConverter.DefaultAttributeConverter; import org.jboss.as.controller.transform.description.DiscardAttributeChecker.DefaultDiscardAttributeChecker; import org.jboss.as.controller.transform.description.RejectAttributeChecker.DefaultRejectAttributeChecker; import org.jboss.dmr.ModelNode; import org.jboss.dmr.ModelType; import org.jboss.dmr.ValueExpression; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * @author <a href="kabir.khan@jboss.com">Kabir Khan</a> */ public class AttributesTestCase { private static PathElement PATH = PathElement.pathElement("toto", "testSubsystem"); private Resource resourceRoot = Resource.Factory.create(); private TransformerRegistry registry = TransformerRegistry.Factory.create(); private ManagementResourceRegistration resourceRegistration; private TransformersSubRegistration transformersSubRegistration; private ModelNode resourceModel; @Before public void setUp() { // Cleanup resourceRoot = Resource.Factory.create(); registry = TransformerRegistry.Factory.create(); resourceRegistration = ManagementResourceRegistration.Factory.forProcessType(ProcessType.EMBEDDED_SERVER).createRegistration(ROOT); // test final Resource toto = Resource.Factory.create(); resourceRoot.registerChild(PATH, toto); resourceModel = toto.getModel(); // Register the description transformersSubRegistration = registry.getServerRegistration(ModelVersion.create(1)); } @Test public void testRejectExpressions() throws Exception { //Set up the model resourceModel.get("reject").set(new ValueExpression("${expr}")); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder().addRejectCheck(RejectAttributeChecker.SIMPLE_EXPRESSIONS, "reject").end(); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); //The rejection does not trigger for resource transformation Assert.assertTrue(model.hasDefined("reject")); ModelNode add = Util.createAddOperation(PathAddress.pathAddress(PATH)); add.get("reject").set(new ValueExpression("${expr}")); OperationTransformer.TransformedOperation transformedAdd = transformOperation(add); Assert.assertTrue(transformedAdd.rejectOperation(success())); ModelNode write = Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "reject", new ModelNode().set(new ValueExpression("${expr}"))); OperationTransformer.TransformedOperation transformedWrite = transformOperation(write); Assert.assertTrue(transformedWrite.rejectOperation(success())); } @Test public void testCustomRejectChecker() throws Exception { //Set up the model resourceModel.get("reject").set(new ValueExpression("${expr}")); DontRejectChecker dontRejectChecker = new DontRejectChecker(); CustomRejectExpressionsChecker rejectAttributeChecker = new CustomRejectExpressionsChecker(); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder() .addRejectCheck(dontRejectChecker, "reject") .addRejectCheck(rejectAttributeChecker, "reject") .end(); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); dontRejectChecker.called = false; rejectAttributeChecker.clear(); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); //The rejection does not trigger for resource transformation //TODO this could be done if 'slave' is >= 7.2.0 Assert.assertTrue(model.hasDefined("reject")); Assert.assertTrue(dontRejectChecker.called); Set<String> rejections = rejectAttributeChecker.getRejections(); Assert.assertEquals(1, rejections.size()); Assert.assertTrue(rejections.contains("reject")); dontRejectChecker.called = false; rejectAttributeChecker.clear(); ModelNode add = Util.createAddOperation(PathAddress.pathAddress(PATH)); add.get("reject").set(new ValueExpression("${expr}")); OperationTransformer.TransformedOperation transformedAdd = transformOperation(add); Assert.assertTrue(transformedAdd.rejectOperation(success())); Assert.assertTrue(dontRejectChecker.called); rejections = rejectAttributeChecker.getRejections(); Assert.assertEquals(1, rejections.size()); Assert.assertTrue(rejections.contains("reject")); dontRejectChecker.called = false; rejectAttributeChecker.clear(); ModelNode write = Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "reject", new ModelNode().set(new ValueExpression("${expr}"))); OperationTransformer.TransformedOperation transformedWrite = transformOperation(write); Assert.assertTrue(transformedWrite.rejectOperation(success())); Assert.assertTrue(dontRejectChecker.called); rejections = rejectAttributeChecker.getRejections(); Assert.assertEquals(1, rejections.size()); Assert.assertTrue(rejections.contains("reject")); } @Test public void testListReject() throws Exception { final ModelNode list = new ModelNode().add("one").add("two").add("three"); resourceModel.get("reject").set(list.clone()); final RejectTwoChecker checker = new RejectTwoChecker(); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder() .addRejectCheck(new RejectAttributeChecker.ListRejectAttributeChecker(checker), "reject") .end(); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); //The rejection does not trigger for resource transformation //TODO this could be done if 'slave' is >= 7.2.0 Assert.assertTrue(model.hasDefined("reject")); Assert.assertEquals(2, checker.count); Assert.assertTrue(checker.rejected); checker.count = 0; checker.rejected = false; ModelNode add = Util.createAddOperation(PathAddress.pathAddress(PATH)); add.get("reject").set(list.clone()); OperationTransformer.TransformedOperation transformedAdd = transformOperation(add); Assert.assertTrue(transformedAdd.rejectOperation(success())); Assert.assertEquals(2, checker.count); Assert.assertTrue(checker.rejected); checker.count = 0; checker.rejected = false; ModelNode write = Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "reject", list.clone()); OperationTransformer.TransformedOperation transformedWrite = transformOperation(write); Assert.assertTrue(transformedWrite.rejectOperation(success())); Assert.assertEquals(2, checker.count); Assert.assertTrue(checker.rejected); } @Test public void testObjectReject() throws Exception { final ModelNode object = new ModelNode(); object.get("0").set("zero"); object.get("1").set("one"); object.get("2").set("two"); object.get("3").set("two"); resourceModel.get("reject").set(object.clone()); final RejectTwoChecker checker = new RejectTwoChecker(); Map<String, RejectAttributeChecker> mapChecker = new HashMap<String, RejectAttributeChecker>(); mapChecker.put("1", checker); mapChecker.put("2", checker); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder() .addRejectCheck(new RejectAttributeChecker.ObjectFieldsRejectAttributeChecker(mapChecker), "reject") .end(); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); //The rejection does not trigger for resource transformation //TODO this could be done if 'slave' is >= 7.2.0 Assert.assertTrue(model.hasDefined("reject")); //The order is unpredicatble since a plain hashmap is used //Assert.assertEquals(2, checker.count); Assert.assertTrue(checker.rejected); checker.count = 0; checker.rejected = false; ModelNode add = Util.createAddOperation(PathAddress.pathAddress(PATH)); add.get("reject").set(object.clone()); OperationTransformer.TransformedOperation transformedAdd = transformOperation(add); Assert.assertTrue(transformedAdd.rejectOperation(success())); //The order is unpredicatble since a plain hashmap is used //Assert.assertEquals(2, checker.count); Assert.assertTrue(checker.rejected); checker.count = 0; checker.rejected = false; ModelNode write = Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "reject", object.clone()); OperationTransformer.TransformedOperation transformedWrite = transformOperation(write); Assert.assertTrue(transformedWrite.rejectOperation(success())); //The order is unpredicatble since a plain hashmap is used //Assert.assertEquals(2, checker.count); Assert.assertTrue(checker.rejected); } @Test public void testDiscardAlways() throws Exception { //Set up the model resourceModel.get("discard").set("nothing"); resourceModel.get("keep").set("here"); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder().setDiscard(DiscardAttributeChecker.ALWAYS, "discard").end(); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); Assert.assertTrue(model.hasDefined("keep")); Assert.assertFalse(model.has("discard")); ModelNode add = Util.createAddOperation(PathAddress.pathAddress(PATH)); add.get("discard").set("nothing"); add.get("keep").set("here"); OperationTransformer.TransformedOperation transformedAdd = transformOperation(add); Assert.assertFalse(transformedAdd.rejectOperation(success())); Assert.assertTrue(transformedAdd.getTransformedOperation().hasDefined("keep")); Assert.assertFalse(transformedAdd.getTransformedOperation().has("discard")); checkOpDiscarded(Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "discard", new ModelNode("nothing"))); checkOpDiscarded(Util.getUndefineAttributeOperation(PathAddress.pathAddress(PATH), "discard")); } @Test public void testDiscardUndefined() throws Exception { //Set up the model resourceModel.get("discard"); resourceModel.get("keep").set("here"); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder().setDiscard(DiscardAttributeChecker.UNDEFINED, "discard", "keep").end(); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); Assert.assertTrue(model.hasDefined("keep")); Assert.assertFalse(model.has("discard")); ModelNode add = Util.createAddOperation(PathAddress.pathAddress(PATH)); add.get("discard"); add.get("keep").set("here"); OperationTransformer.TransformedOperation transformedAdd = transformOperation(add); Assert.assertFalse(transformedAdd.rejectOperation(success())); Assert.assertTrue(transformedAdd.getTransformedOperation().hasDefined("keep")); Assert.assertFalse(transformedAdd.getTransformedOperation().has("discard")); checkOpDiscarded(Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "discard", new ModelNode())); checkWriteOp(Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "discard", new ModelNode("nothing")), "discard", new ModelNode("nothing")); } @Test public void testDiscardNotHappeningWithExpressions() throws Exception { //Set up the model resourceModel.get("discard").set(new ValueExpression("${xxx}")); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder().setDiscard(new DefaultDiscardAttributeChecker(false, false) { @Override public boolean isValueDiscardable(PathAddress address, String attributeName, ModelNode attributeValue, TransformationContext context) { return true; } }, "discard").end(); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); Assert.assertEquals(new ModelNode().set(new ValueExpression("${xxx}")), model.get("discard")); ModelNode add = Util.createAddOperation(PathAddress.pathAddress(PATH)); add.get("discard").set(new ValueExpression("${xxx}")); OperationTransformer.TransformedOperation transformedAdd = transformOperation(add); Assert.assertFalse(transformedAdd.rejectOperation(success())); Assert.assertEquals(add, transformedAdd.getTransformedOperation()); checkWriteOp(Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "discard", new ModelNode().set(new ValueExpression("${xxx}"))), "discard", new ModelNode().set(new ValueExpression("${xxx}"))); } @Test public void testDiscardDefaultValue() throws Exception { //Set up the model resourceModel.get("discard").set("default"); resourceModel.get("keep").set("non-default"); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder().setDiscard(new DefaultDiscardAttributeChecker(false, true) { @Override public boolean isValueDiscardable(PathAddress address, String attributeName, ModelNode attributeValue, TransformationContext context) { if (attributeName.equals("discard") || attributeName.equals("keep")) { if (attributeValue.asString().equals("default")) { return true; } } return false; } }, "discard", "keep").end(); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); Assert.assertTrue(model.hasDefined("keep")); Assert.assertFalse(model.has("discard")); ModelNode add = Util.createAddOperation(PathAddress.pathAddress(PATH)); add.get("discard"); add.get("keep").set("here"); OperationTransformer.TransformedOperation transformedAdd = transformOperation(add); Assert.assertFalse(transformedAdd.rejectOperation(success())); Assert.assertTrue(transformedAdd.getTransformedOperation().hasDefined("keep")); Assert.assertFalse(transformedAdd.getTransformedOperation().has("discard")); checkOpDiscarded(Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "discard", new ModelNode("default"))); checkWriteOp(Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "discard", new ModelNode("something")), "discard", new ModelNode("something")); } @Test public void testRenameAttribute() throws Exception { resourceModel.get("old").set("value"); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder().addRename("old", "new").end(); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); Assert.assertEquals(1, model.keys().size()); Assert.assertEquals("value", model.get("new").asString()); ModelNode add = Util.createAddOperation(PathAddress.pathAddress(PATH)); add.get("old").set("value"); OperationTransformer.TransformedOperation transformedAdd = transformOperation(add); Assert.assertFalse(transformedAdd.rejectOperation(success())); Assert.assertFalse(transformedAdd.getTransformedOperation().hasDefined("old")); Assert.assertEquals("value", transformedAdd.getTransformedOperation().get("new").asString()); checkWriteOp(Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "old", new ModelNode("value")), "new", new ModelNode("value")); } @Test public void testConvertValue() throws Exception { resourceModel.get("value1").set("one"); resourceModel.get("value2").set("two"); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder().setValueConverter(new DefaultAttributeConverter() { @Override public void convertAttribute(PathAddress address, String name, ModelNode attributeValue, TransformationContext context) { if (name.equals("value2") && attributeValue.asString().equals("two")) { attributeValue.set(1); } } }, "value1", "value2").end(); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); Assert.assertEquals(2, model.keys().size()); Assert.assertEquals("one", model.get("value1").asString()); Assert.assertEquals(ModelType.INT, model.get("value2").getType()); Assert.assertEquals(1, model.get("value2").asInt()); ModelNode add = Util.createAddOperation(PathAddress.pathAddress(PATH)); add.get("value1").set("one"); add.get("value2").set("two"); OperationTransformer.TransformedOperation transformedAdd = transformOperation(add); Assert.assertFalse(transformedAdd.rejectOperation(success())); Assert.assertEquals("one", transformedAdd.getTransformedOperation().get("value1").asString()); Assert.assertEquals(ModelType.INT, transformedAdd.getTransformedOperation().get("value2").getType()); Assert.assertEquals(1, transformedAdd.getTransformedOperation().get("value2").asInt()); checkWriteOp(Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "value1", new ModelNode("value")), "value1", new ModelNode("value")); checkWriteOp(Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "value2", new ModelNode("two")), "value2", new ModelNode(1)); } @Test public void testAddValue() throws Exception { resourceModel.get("old").set("existing"); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder().setValueConverter(new DefaultAttributeConverter() { @Override public void convertAttribute(PathAddress address, String name, ModelNode attributeValue, TransformationContext context) { attributeValue.set("extra"); } }, "added").end(); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); Assert.assertEquals(2, model.keys().size()); Assert.assertEquals("existing", model.get("old").asString()); Assert.assertEquals("extra", model.get("added").asString()); ModelNode add = Util.createAddOperation(PathAddress.pathAddress(PATH)); add.get("old").set("existing"); OperationTransformer.TransformedOperation transformedAdd = transformOperation(add); Assert.assertFalse(transformedAdd.rejectOperation(success())); Assert.assertEquals("existing", transformedAdd.getTransformedOperation().get("old").asString()); Assert.assertEquals("extra", transformedAdd.getTransformedOperation().get("added").asString()); //Can't write to this added attribute } @Test public void testComplexRejectAndModify() throws Exception { resourceModel.get("one").set("a"); resourceModel.get("two").set("b"); resourceModel.get("three").set("TRES"); resourceModel.get("four"); resourceModel.get("five"); resourceModel.get("six"); Map<String,String> renames = new HashMap<String, String>(); renames.put("one", "uno"); renames.put("two", "dos"); CustomRejectExpressionsChecker rejectAttributeChecker = new CustomRejectExpressionsChecker(); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder() .addRejectCheck(rejectAttributeChecker, "one", "two") .setValueConverter(new DefaultAttributeConverter() { @Override public void convertAttribute(PathAddress address, String name, ModelNode attributeValue, TransformationContext context) { attributeValue.set("NEW"); } }, "new") .setDiscard(DiscardAttributeChecker.UNDEFINED, "four", "five") .setDiscard(DiscardAttributeChecker.UNDEFINED, "six") .setValueConverter(new DefaultAttributeConverter() { @Override public void convertAttribute(PathAddress address, String name, ModelNode attributeValue, TransformationContext context) { if (name.equals("one")) { attributeValue.set("UNO"); } else if (name.equals("two")) { attributeValue.set("DOS"); } } }, "one", "two") .addRenames(renames) .addRename("three", "tres") //.rename(Collections.singletonMap("four", "cuatro")) .end(); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); //Try first with no expressions rejectAttributeChecker.clear(); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); Assert.assertEquals(4, model.keys().size()); Assert.assertEquals("NEW", model.get("new").asString()); Assert.assertEquals("UNO", model.get("uno").asString()); Assert.assertEquals("DOS", model.get("dos").asString()); Assert.assertEquals("TRES", model.get("tres").asString()); Set<String> rejections = rejectAttributeChecker.getRejections(); Assert.assertEquals(0, rejections.size()); final ModelNode add = Util.createAddOperation(PathAddress.pathAddress(PATH)); add.get("one").set("a"); add.get("two").set("b"); add.get("three").set("TRES"); add.get("four"); add.get("five"); add.get("six"); final OperationTransformer.TransformedOperation transformedAdd = transformOperation(add); Assert.assertFalse(transformedAdd.rejectOperation(success())); final ModelNode transAdd = transformedAdd.getTransformedOperation(); transAdd.remove(OP); transAdd.remove(OP_ADDR); Assert.assertEquals(4, transAdd.keys().size()); Assert.assertEquals("NEW", transAdd.get("new").asString()); Assert.assertEquals("UNO", transAdd.get("uno").asString()); Assert.assertEquals("DOS", transAdd.get("dos").asString()); Assert.assertEquals("TRES", transAdd.get("tres").asString()); rejections = rejectAttributeChecker.getRejections(); Assert.assertEquals(0, rejections.size()); checkWriteOp(Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "one", new ModelNode("a")), "uno", new ModelNode("UNO")); checkWriteOp(Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "two", new ModelNode("b")), "dos", new ModelNode("DOS")); checkWriteOp(Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "three", new ModelNode("THREE")), "tres", new ModelNode("THREE")); checkOpDiscarded(Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "four", new ModelNode())); checkOpDiscarded(Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "five", new ModelNode())); checkOpDiscarded(Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "six", new ModelNode())); rejections = rejectAttributeChecker.getRejections(); Assert.assertEquals(0, rejections.size()); //Check that expressions get rejected resourceModel.clear(); resourceModel.get("one").set(new ValueExpression("${test}")); resourceModel.get("two").set("b"); resourceModel.get("three").set("TRES"); resourceModel.get("four"); resourceModel.get("five"); resourceModel.get("six"); rejectAttributeChecker.clear(); final Resource resource2 = transformResource(); Assert.assertNotNull(resource2); final Resource toto2 = resource2.getChild(PATH); Assert.assertNotNull(toto2); final ModelNode model2 = toto2.getModel(); Assert.assertEquals(4, model2.keys().size()); Assert.assertEquals("NEW", model2.get("new").asString()); Assert.assertEquals("UNO", model2.get("uno").asString()); Assert.assertEquals("DOS", model2.get("dos").asString()); Assert.assertEquals("TRES", model2.get("tres").asString()); rejections = rejectAttributeChecker.getRejections(); Assert.assertEquals(1, rejections.size()); Assert.assertTrue(rejections.contains("one")); rejectAttributeChecker.clear(); final ModelNode add2 = Util.createAddOperation(PathAddress.pathAddress(PATH)); add2.get("one").set(new ValueExpression("${test}")); add2.get("two").set("b"); add2.get("three").set("TRES"); add2.get("four"); add2.get("five"); add2.get("six"); final OperationTransformer.TransformedOperation transformedAdd2 = transformOperation(add2); Assert.assertTrue(transformedAdd2.rejectOperation(success())); rejections = rejectAttributeChecker.getRejections(); Assert.assertEquals(1, rejections.size()); Assert.assertTrue(rejections.contains("one")); rejectAttributeChecker.clear(); OperationTransformer.TransformedOperation write = transformOperation(Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "one", new ModelNode().set(new ValueExpression("${test}")))); Assert.assertTrue(write.rejectOperation(success())); rejections = rejectAttributeChecker.getRejections(); Assert.assertEquals(1, rejections.size()); Assert.assertTrue(rejections.contains("one")); } @Test public void testNameFromAddressConverter() throws Exception { //Set up the model resourceModel.get("value").set("test"); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder().setValueConverter(AttributeConverter.NAME_FROM_ADDRESS, "name").end(); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); Assert.assertEquals(2, model.keys().size()); Assert.assertEquals("test", model.get("value").asString()); Assert.assertEquals(PATH.getValue(), model.get("name").asString()); ModelNode add = Util.createAddOperation(PathAddress.pathAddress(PATH)); add.get("value").set("test"); OperationTransformer.TransformedOperation transformedAdd = transformOperation(add); Assert.assertEquals("test", transformedAdd.getTransformedOperation().get("value").asString()); Assert.assertEquals(PATH.getValue(), transformedAdd.getTransformedOperation().get("name").asString()); //No point in testing write-attribute for a new attribute } @Test public void testAccessOtherValue() throws Exception { //Set up the model resourceModel.get("checked").set("test"); resourceModel.get("other").set("value"); VisibilityCheckerAndConverter checker = new VisibilityCheckerAndConverter(); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder() .addRejectCheck(checker, "checked") .setDiscard(checker, "checked") .setValueConverter(checker, "checked") .end(); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); //The rejection does not trigger for resource transformation Assert.assertTrue(model.hasDefined("checked")); checker.checkValues("value"); checker.reset(); ModelNode add = Util.createAddOperation(PathAddress.pathAddress(PATH)); add.get("checked").set("test"); add.get("other").set("value"); OperationTransformer.TransformedOperation transformedAdd = transformOperation(add); Assert.assertFalse(transformedAdd.rejectOperation(success())); checker.checkValues("value"); checker.reset(); ModelNode write = Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "checked", new ModelNode("test")); OperationTransformer.TransformedOperation transformedWrite = transformOperation(write); Assert.assertFalse(transformedWrite.rejectOperation(success())); checker.checkValues("value"); } @Test public void testConvertVsAdd() throws Exception { resourceModel.get("convert").set("test"); resourceModel.get("undefined"); AttributeNameValueConverter converter = new AttributeNameValueConverter(); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder() .setValueConverter(converter, "convert", "undefined", "new", "dontAdd") .end(); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); Assert.assertEquals(3, model.keys().size()); Assert.assertEquals("convert", model.get("convert").asString()); Assert.assertEquals("undefined", model.get("undefined").asString()); Assert.assertEquals("new", model.get("new").asString()); } @Test public void testSimpleReject() throws Exception { //Set up the model resourceModel.get("reject").set(true); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder().addRejectCheck(new RejectAttributeChecker.SimpleRejectAttributeChecker(new ModelNode(true)), "reject").end(); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); //The rejection does not trigger for resource transformation Assert.assertTrue(model.hasDefined("reject")); ModelNode add = Util.createAddOperation(PathAddress.pathAddress(PATH)); add.get("reject").set(true); OperationTransformer.TransformedOperation transformedAdd = transformOperation(add); Assert.assertTrue(transformedAdd.rejectOperation(success())); ModelNode write = Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "reject", new ModelNode().set(true)); OperationTransformer.TransformedOperation transformedWrite = transformOperation(write); Assert.assertTrue(transformedWrite.rejectOperation(success())); } @Test public void testSimpleAccept() throws Exception { //Set up the model resourceModel.get("reject").set(true); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder().addRejectCheck(new RejectAttributeChecker.SimpleAcceptAttributeChecker(new ModelNode(false)), "reject").end(); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); //The rejection does not trigger for resource transformation Assert.assertTrue(model.hasDefined("reject")); ModelNode add = Util.createAddOperation(PathAddress.pathAddress(PATH)); add.get("reject").set(true); OperationTransformer.TransformedOperation transformedAdd = transformOperation(add); Assert.assertTrue(transformedAdd.rejectOperation(success())); ModelNode write = Util.getWriteAttributeOperation(PathAddress.pathAddress(PATH), "reject", new ModelNode().set(true)); OperationTransformer.TransformedOperation transformedWrite = transformOperation(write); Assert.assertTrue(transformedWrite.rejectOperation(success())); } @Test public void testOriginalModelDoesNotChange() throws Exception { //Set up the model resourceModel.get("discard").set(true); final ResourceTransformationDescriptionBuilder builder = TransformationDescriptionBuilder.Factory.createInstance(PATH); builder.getAttributeBuilder().setDiscard(new DiscardAttributeChecker.DefaultDiscardAttributeChecker() { @Override protected boolean isValueDiscardable(PathAddress address, String attributeName, ModelNode attributeValue, TransformationContext context) { //Same as DiscardAttributeChecker.ALWAYS, but being able to set a breakpoint here is useful for me return true; } }, "discard"); builder.setCustomResourceTransformer(new ResourceTransformer() { @Override public void transformResource(ResourceTransformationContext context, PathAddress address, Resource resource) throws OperationFailedException { Resource untransformed = context.readResource(PathAddress.EMPTY_ADDRESS); ModelNode model = untransformed.getModel(); Assert.assertTrue(model.hasDefined("discard")); Assert.assertTrue(model.get("discard").asBoolean()); context.addTransformedResource(PathAddress.EMPTY_ADDRESS, resource); } }); TransformationDescription.Tools.register(builder.build(), transformersSubRegistration); final Resource resource = transformResource(); Assert.assertNotNull(resource); final Resource toto = resource.getChild(PATH); Assert.assertNotNull(toto); final ModelNode model = toto.getModel(); Assert.assertFalse(model.hasDefined("discard")); } private void checkWriteOp(ModelNode write, String name, ModelNode value) throws OperationFailedException{ OperationTransformer.TransformedOperation transformedWrite = transformOperation(write); Assert.assertFalse(transformedWrite.rejectOperation(success())); ModelNode transWrite = transformedWrite.getTransformedOperation(); Assert.assertEquals(name, transWrite.get(NAME).asString()); Assert.assertEquals(value, transWrite.get(VALUE)); Assert.assertEquals(value.getType(), transWrite.get(VALUE).getType()); } private void checkOpDiscarded(ModelNode write) throws OperationFailedException { OperationTransformer.TransformedOperation transformedWrite = transformOperation(write); Assert.assertFalse(transformedWrite.rejectOperation(success())); Assert.assertNull(transformedWrite.getTransformedOperation()); } private Resource transformResource() throws OperationFailedException { final TransformationTarget target = create(registry, ModelVersion.create(1)); final ResourceTransformationContext context = createContext(target); return getTransfomers(target).transformResource(context, resourceRoot); } private OperationTransformer.TransformedOperation transformOperation(final ModelNode operation) throws OperationFailedException { final TransformationTarget target = create(registry, ModelVersion.create(1)); final TransformationContext context = createContext(target); return getTransfomers(target).transformOperation(context, operation); } private ResourceTransformationContext createContext(final TransformationTarget target) { return Transformers.Factory.create(target, resourceRoot, resourceRegistration, ExpressionResolver.TEST_RESOLVER, RunningMode.NORMAL, ProcessType.STANDALONE_SERVER, null); } private Transformers getTransfomers(final TransformationTarget target) { return Transformers.Factory.create(target); } protected TransformationTarget create(final TransformerRegistry registry, ModelVersion version) { return create(registry, version, TransformationTarget.TransformationTargetType.SERVER); } protected TransformationTarget create(final TransformerRegistry registry, ModelVersion version, TransformationTarget.TransformationTargetType type) { return TransformationTargetImpl.create(null, registry, version, Collections.<PathAddress, ModelVersion>emptyMap(), type); } private static final ResourceDefinition ROOT = new SimpleResourceDefinition(PathElement.pathElement("test"), new NonResolvingResourceDescriptionResolver()); private static ModelNode success() { final ModelNode result = new ModelNode(); result.get(ModelDescriptionConstants.OUTCOME).set(ModelDescriptionConstants.SUCCESS); result.get(ModelDescriptionConstants.RESULT); return result; } private static ModelNode failed() { final ModelNode result = new ModelNode(); result.get(ModelDescriptionConstants.OUTCOME).set(ModelDescriptionConstants.FAILED); result.get(ModelDescriptionConstants.FAILURE_DESCRIPTION).set("failed"); result.get(ModelDescriptionConstants.RESULT); return result; } private static class DontRejectChecker extends DefaultRejectAttributeChecker { boolean called; @Override public boolean rejectAttribute(PathAddress address, String attributeName, ModelNode attributeValue, TransformationContext context) { called = true; return false; } @Override public String getRejectionLogMessage(Map<String, ModelNode> attributes) { return "dont reject: " + attributes; } } private static class CustomRejectExpressionsChecker implements RejectAttributeChecker { Map<String, Boolean> rejected = new HashMap<String, Boolean>(); @Override public boolean rejectOperationParameter(PathAddress address, String attributeName, ModelNode attributeValue, ModelNode operation, TransformationContext context) { boolean rejected = SIMPLE_EXPRESSIONS.rejectOperationParameter(address, attributeName, attributeValue, operation, context); this.rejected.put(attributeName, rejected); return rejected; } @Override public boolean rejectResourceAttribute(PathAddress address, String attributeName, ModelNode attributeValue, TransformationContext context) { boolean rejected = SIMPLE_EXPRESSIONS.rejectResourceAttribute(address, attributeName, attributeValue, context); this.rejected.put(attributeName, rejected); return rejected; } @Override public String getRejectionLogMessageId() { return SIMPLE_EXPRESSIONS.getRejectionLogMessageId(); } @Override public String getRejectionLogMessage(Map<String, ModelNode> attributes) { return SIMPLE_EXPRESSIONS.getRejectionLogMessage(attributes); } void clear() { rejected.clear(); } Set<String> getRejections() { Set<String> rejections = new HashSet<String>(); for (Map.Entry<String, Boolean> entry : rejected.entrySet()) { if (entry.getValue()) { rejections.add(entry.getKey()); } } return rejections; } } private static class RejectTwoChecker extends DefaultRejectAttributeChecker { int count; boolean rejected; @Override public boolean rejectAttribute(PathAddress address, String attributeName, ModelNode attributeValue, TransformationContext context) { count++; rejected = attributeValue.asString().equals("two"); return rejected; } @Override public String getRejectionLogMessage(Map<String, ModelNode> attributes) { return "Reject Two: " + attributes; } } private static class VisibilityCheckerAndConverter implements RejectAttributeChecker, AttributeConverter, DiscardAttributeChecker { String convertValue; String discardValue; String rejectValue; void checkValues(String expected) { Assert.assertEquals(expected, discardValue); Assert.assertEquals(expected, rejectValue); Assert.assertEquals(expected, convertValue); } void reset() { convertValue = null; discardValue = null; rejectValue = null; } @Override public boolean isDiscardExpressions() { return false; } @Override public boolean isDiscardUndefined() { return false; } @Override public boolean isOperationParameterDiscardable(PathAddress address, String attributeName, ModelNode attributeValue, ModelNode operation, TransformationContext context) { if (operation.get(OP).asString().equals(WRITE_ATTRIBUTE_OPERATION) || operation.get(OP).asString().equals(UNDEFINE_ATTRIBUTE_OPERATION)) { discardValue = context.readResource(PathAddress.EMPTY_ADDRESS).getModel().get("other").asString(); } else { discardValue = operation.get("other").asString(); } return false; } @Override public boolean isResourceAttributeDiscardable(PathAddress address, String attributeName, ModelNode attributeValue, TransformationContext context) { discardValue = context.readResource(PathAddress.EMPTY_ADDRESS).getModel().get("other").asString(); return false; } @Override public void convertOperationParameter(PathAddress address, String name, ModelNode attributeValue, ModelNode operation, TransformationContext context) { if (operation.get(OP).asString().equals(WRITE_ATTRIBUTE_OPERATION) || operation.get(OP).asString().equals(UNDEFINE_ATTRIBUTE_OPERATION)) { convertValue = context.readResource(PathAddress.EMPTY_ADDRESS).getModel().get("other").asString(); } else { convertValue = operation.get("other").asString(); } } @Override public void convertResourceAttribute(PathAddress address, String name, ModelNode attributeValue, TransformationContext context) { convertValue = context.readResource(PathAddress.EMPTY_ADDRESS).getModel().get("other").asString(); } @Override public boolean rejectOperationParameter(PathAddress address, String attributeName, ModelNode attributeValue, ModelNode operation, TransformationContext context) { if (operation.get(OP).asString().equals(WRITE_ATTRIBUTE_OPERATION) || operation.get(OP).asString().equals(UNDEFINE_ATTRIBUTE_OPERATION)) { rejectValue = context.readResource(PathAddress.EMPTY_ADDRESS).getModel().get("other").asString(); } else { rejectValue = operation.get("other").asString(); } return false; } @Override public boolean rejectResourceAttribute(PathAddress address, String attributeName, ModelNode attributeValue, TransformationContext context) { rejectValue = context.readResource(PathAddress.EMPTY_ADDRESS).getModel().get("other").asString(); return false; } @Override public String getRejectionLogMessageId() { return getRejectionLogMessage(Collections.<String, ModelNode>emptyMap()); } @Override public String getRejectionLogMessage(Map<String, ModelNode> attributes) { return "Visibility " + attributes; } } private static class AttributeNameValueConverter extends DefaultAttributeConverter { @Override protected void convertAttribute(PathAddress address, String name, ModelNode attributeValue, TransformationContext context) { if (!name.equals("dontAdd")) { attributeValue.set(name); } } } }