private void populateModelWithCoordinatorEnvConfig(ModelNode operation, ModelNode coordEnvModel) throws OperationFailedException { TransactionSubsystemRootResourceDefinition.STATISTICS_ENABLED.validateAndSet( operation, coordEnvModel); TransactionSubsystemRootResourceDefinition.ENABLE_STATISTICS.validateAndSet( operation, coordEnvModel); TransactionSubsystemRootResourceDefinition.ENABLE_TSM_STATUS.validateAndSet( operation, coordEnvModel); TransactionSubsystemRootResourceDefinition.DEFAULT_TIMEOUT.validateAndSet( operation, coordEnvModel); ModelNode mceVal = coordEnvModel.get(TransactionSubsystemRootResourceDefinition.ENABLE_STATISTICS.getName()); if (mceVal.isDefined()) { ModelNode seVal = coordEnvModel.get( TransactionSubsystemRootResourceDefinition.STATISTICS_ENABLED.getName()); if (seVal.isDefined() && !seVal.equals(mceVal)) { throw TransactionLogger.ROOT_LOGGER.inconsistentStatisticsSettings( TransactionSubsystemRootResourceDefinition.STATISTICS_ENABLED.getName(), TransactionSubsystemRootResourceDefinition.ENABLE_STATISTICS.getName()); } seVal.set(mceVal); mceVal.set(new ModelNode()); } }
public static ModelNode parsePossibleExpression(String value) { ModelNode result = new ModelNode(); if (isExpression(value)) { result.set(new ValueExpression(value)); } else { result.set(value); } return result; }
/** * Finds a value in the given {@code operationObject} whose key matches this attribute's {@link * #getName() name}, resolves it and validates it using this attribute's {@link #getValidator() * validator}. If the value is undefined and a {@link #getDefaultValue() default value} is * available, the default value is used. * * @param operationObject model node of type {@link ModelType#OBJECT}, typically representing an * operation request * @return the resolved value, possibly the default value if the operation does not have a defined * value matching this attribute's name * @throws OperationFailedException if the value is not valid */ public ModelNode validateResolvedOperation(final ModelNode operationObject) throws OperationFailedException { final ModelNode node = new ModelNode(); if (operationObject.has(name)) { node.set(operationObject.get(name)); } if (!node.isDefined() && defaultValue.isDefined()) { node.set(defaultValue); } final ModelNode resolved = node.resolve(); validator.validateParameter(name, resolved); return resolved; }
private ModelNode createDeploymentOperation( ModelNode content, PathAddress... serverGroupAddressses) { ModelNode composite = createEmptyOperation(COMPOSITE, PathAddress.EMPTY_ADDRESS); ModelNode steps = composite.get(STEPS); ModelNode step1 = steps.add(); step1.set(createAddOperation(ROOT_DEPLOYMENT_ADDRESS)); step1.get(CONTENT).add(content); for (PathAddress serverGroup : serverGroupAddressses) { ModelNode sg = steps.add(); sg.set(createAddOperation(serverGroup)); sg.get(ENABLED).set(true); } return composite; }
static void sendError(HttpServerExchange exchange, boolean isGet, boolean encode, String msg) { if (encode) { try { ModelNode response = new ModelNode(); response.set(msg); ByteArrayOutputStream bout = new ByteArrayOutputStream(); response.writeBase64(bout); byte[] bytes = bout.toByteArray(); exchange .getResponseHeaders() .put(Headers.CONTENT_TYPE, APPLICATION_DMR_ENCODED + ";" + UTF_8); exchange.getResponseHeaders().put(Headers.CONTENT_LENGTH, String.valueOf(bytes.length)); exchange.setResponseCode(500); exchange.getResponseSender().send(new String(bytes), IoCallback.END_EXCHANGE); } catch (IOException e) { // fallback, should not happen sendError(exchange, isGet, false, msg); } } else { byte[] bytes = msg.getBytes(); exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, TEXT_PLAIN + ";" + UTF_8); exchange.getResponseHeaders().put(Headers.CONTENT_LENGTH, String.valueOf(bytes.length)); exchange.setResponseCode(500); exchange.getResponseSender().send(msg, IoCallback.END_EXCHANGE); } }
private void setProps(ModelNode requestProperties) throws Exception { props = new TreeSet<RequestProp>(); if (opName.equals("add")) { UserObject usrObj = (UserObject) node.getUserObject(); props.add( new RequestProp( "/" + usrObj.getName() + "=<name>/", "Resource name for the new " + usrObj.getName(), true, ModelType.STRING)); } if (opName.equals("write-attribute") && node.isLeaf()) { ModelNode nameNode = requestProperties.get("name"); nameNode .get("type") .set(ModelType.UNDEFINED); // undefined type will display as uneditable String UserObject usrObj = (UserObject) node.getUserObject(); ModelNode nameNodeValue = new ModelNode(); nameNodeValue.set(usrObj.getName()); props.add(new RequestProp("name", requestProperties.get("name"), nameNodeValue)); ModelNode rscDesc = cliGuiCtx.getExecutor().doCommand(node.addressPath() + ":read-resource-description"); ModelNode valueNode = rscDesc.get("result", "attributes", usrObj.getName()); valueNode.get("required").set(false); // value is never required for write-attribute ModelNode valueNodeValue = usrObj.getBackingNode().get(usrObj.getName()); props.add(new RequestProp("value", valueNode, valueNodeValue)); return; } for (Property prop : requestProperties.asPropertyList()) { props.add(new RequestProp(prop.getName(), prop.getValue(), null)); } }
/** * Creates CliCommandAction for adding a Virtual-Server * * @param server Virtual-Server * @return created CliCommandAction for adding the Virtual-Server * @throws CliScriptException if required attributes for a creation of the CLI command of the * Virtual-Server are missing or are empty (server-name) */ public static CliCommandAction createVirtualServerCliAction(VirtualServerBean server) throws CliScriptException { String errMsg = "in virtual-server (engine in AS5) must be set"; Utils.throwIfBlank(server.getVirtualServerName(), errMsg, "Server name"); ModelNode serverCmd = new ModelNode(); serverCmd.get(ClientConstants.OP).set(ClientConstants.ADD); serverCmd.get(ClientConstants.OP_ADDR).add("subsystem", "web"); serverCmd.get(ClientConstants.OP_ADDR).add("virtual-server", server.getVirtualServerName()); if (server.getAliasName() != null) { ModelNode aliasesNode = new ModelNode(); for (String alias : server.getAliasName()) { ModelNode aliasNode = new ModelNode(); aliasNode.set(alias); aliasesNode.add(aliasNode); } serverCmd.get("alias").set(aliasesNode); } CliApiCommandBuilder builder = new CliApiCommandBuilder(serverCmd); builder.addProperty("enable-welcome-root", server.getEnableWelcomeRoot()); builder.addProperty("default-web-module", server.getDefaultWebModule()); return new CliCommandAction( ServerMigrator.class, createVirtualServerScript(server), builder.getCommand()); }
@Override public void execute(OperationContext context, ModelNode operation) throws OperationFailedException { validator.validate(operation); ThreadMXBean mbean = ManagementFactory.getThreadMXBean(); try { long id = operation.require(PlatformMBeanConstants.ID).asLong(); ThreadInfo info = null; if (operation.hasDefined(PlatformMBeanConstants.MAX_DEPTH)) { info = mbean.getThreadInfo(id, operation.require(PlatformMBeanConstants.MAX_DEPTH).asInt()); } else { info = mbean.getThreadInfo(id); } final ModelNode result = context.getResult(); if (info != null) { result.set(PlatformMBeanUtil.getDetypedThreadInfo(info, mbean.isThreadCpuTimeSupported())); } } catch (SecurityException e) { throw new OperationFailedException(new ModelNode().set(e.toString())); } context.completeStep(); }
@Override void execute(final ModelNode operation, final SocketBinding binding, final ModelNode result) { ManagedBinding managedBinding = binding.getManagedBinding(); if (managedBinding != null) { int port = managedBinding.getBindAddress().getPort(); result.set(port); } }
protected void addHeaders(CommandContext ctx, ModelNode request) throws CommandFormatException { if (!headers.isPresent(ctx.getParsedCommandLine())) { return; } final ModelNode headersNode = headers.toModelNode(ctx); final ModelNode opHeaders = request.get(Util.OPERATION_HEADERS); opHeaders.set(headersNode); }
/** {@inheritDoc} */ public void convertAttribute( PathAddress address, String name, ModelNode attributeValue, TransformationContext context) { PathElement element = address.getLastElement(); attributeValue.set(element.getValue()); }
@Override void execute(final ModelNode operation, final SocketBinding binding, final ModelNode result) { ManagedBinding managedBinding = binding.getManagedBinding(); if (managedBinding != null) { InetAddress addr = managedBinding.getBindAddress().getAddress(); result.set(addr.getHostAddress()); } }
private ModelNode createDeploymentReplaceOperation( ModelNode content, PathAddress... serverGroupAddressses) { ModelNode composite = createEmptyOperation(COMPOSITE, PathAddress.EMPTY_ADDRESS); ModelNode steps = composite.get(STEPS); ModelNode step1 = steps.add(); step1.set(createAddOperation(ROOT_REPLACEMENT_ADDRESS)); step1.get(RUNTIME_NAME).set(TEST); step1.get(CONTENT).add(content); for (PathAddress serverGroup : serverGroupAddressses) { ModelNode sgr = steps.add(); sgr.set(createEmptyOperation(REPLACE_DEPLOYMENT, serverGroup)); sgr.get(ENABLED).set(true); sgr.get(NAME).set(REPLACEMENT); sgr.get(TO_REPLACE).set(TEST); } return composite; }
void updateModel(final OperationContext context, ModelNode model, ModelNode listAttribute) throws OperationFailedException { ModelNode value = VALUE.resolveModelAttribute(context, model); ModelNode index = INDEX.resolveModelAttribute(context, model); List<ModelNode> res = new ArrayList<>(listAttribute.asList()); if (index.isDefined()) { res.remove(index.asInt()); } else { res.remove(value); } listAttribute.set(res); }
private ModelNode unmaskUsersPasswords(OperationContext context, ModelNode users) throws OperationFailedException { users = users.clone(); for (Property property : users.get(USER).asPropertyList()) { // Don't use the value from property as it is a clone and does not update the returned users // ModelNode. ModelNode user = users.get(USER, property.getName()); if (user.hasDefined(PASSWORD)) { // TODO This will be cleaned up once it uses attribute definitions user.set(PASSWORD, context.resolveExpressions(user.get(PASSWORD)).asString()); } } return users; }
@Test public void testPropertyValueTypeConverter() { ModelNode description = createDescription(ModelType.PROPERTY, ModelType.INT); TypeConverter converter = getConverter(description); ModelNode node = new ModelNode(); node.set("name", 1); node.protect(); Assert.assertEquals(SimpleType.STRING, converter.getOpenType()); String dmr = assertCast(String.class, converter.fromModelNode(node)); Assert.assertEquals(node, ModelNode.fromString(dmr)); Assert.assertEquals(dmr, assertCast(String.class, converter.fromModelNode(node))); assertToArray(converter, dmr); }
/** * Update the model to hold domain level configuration. * * @param rootResource the root resource to be updated. * @param environment the host controller's configuration environment */ public static void updateCoreModel( final Resource rootResource, HostControllerEnvironment environment) { final ModelNode rootModel = rootResource.getModel(); rootModel.get(RELEASE_VERSION).set(Version.AS_VERSION); rootModel.get(RELEASE_CODENAME).set(Version.AS_RELEASE_CODENAME); rootModel.get(MANAGEMENT_MAJOR_VERSION).set(Version.MANAGEMENT_MAJOR_VERSION); rootModel.get(MANAGEMENT_MINOR_VERSION).set(Version.MANAGEMENT_MINOR_VERSION); // Community uses UNDEF values ModelNode nameNode = rootModel.get(PRODUCT_NAME); ModelNode versionNode = rootModel.get(PRODUCT_VERSION); if (environment != null) { String productName = environment.getProductConfig().getProductName(); String productVersion = environment.getProductConfig().getProductVersion(); if (productName != null) { nameNode.set(productName); } if (productVersion != null) { versionNode.set(productVersion); } } }
private void addManagementComponentComponent( ModelNode realm, ModelNode parentAddress, String key, List<ModelNode> updates) { for (String currentComponent : realm.get(key).keys()) { ModelNode addComponent = new ModelNode(); // First take the properties to pass over. addComponent.set(realm.get(key, currentComponent)); // Now convert it to an operation by adding a name and address. ModelNode identityAddress = parentAddress.clone().add(key, currentComponent); addComponent.get(OP).set(ADD); addComponent.get(OP_ADDR).set(identityAddress); updates.add(addComponent); } }
/** * Creates and returns a {@link org.jboss.dmr.ModelNode} using the given {@code value} after first * validating the node against {@link #getValidator() this object's validator}. * * <p>If {@code value} is {@code null} and a {@link #getDefaultValue() default value} is * available, the value of that default value will be used. * * @param value the value. Will be {@link String#trim() trimmed} before use if not {@code null}. * @param location current location of the parser's {@link javax.xml.stream.XMLStreamReader}. Used * for any exception message * @return {@code ModelNode} representing the parsed value * @throws javax.xml.stream.XMLStreamException if {@code value} is not valid */ public ModelNode parse(final String value, final Location location) throws XMLStreamException { final String trimmed = value == null ? null : value.trim(); ModelNode node; if (trimmed != null) { if (isAllowExpression()) { node = ParseUtils.parsePossibleExpression(trimmed); } else { node = new ModelNode().set(trimmed); } if (node.getType() != ModelType.EXPRESSION) { // Convert the string to the expected type switch (getType()) { case BIG_DECIMAL: node.set(node.asBigDecimal()); break; case BIG_INTEGER: node.set(node.asBigInteger()); break; case BOOLEAN: node.set(node.asBoolean()); break; case BYTES: node.set(node.asBytes()); break; case DOUBLE: node.set(node.asDouble()); break; case INT: node.set(node.asInt()); break; case LONG: node.set(node.asLong()); break; } } } else if (getDefaultValue().isDefined()) { node = new ModelNode().set(getDefaultValue()); } else { node = new ModelNode(); } try { getValidator().validateParameter(getXmlName(), node); } catch (OperationFailedException e) { throw new XMLStreamException(e.getFailureDescription().toString(), location); } return node; }
void updateModel(final OperationContext context, ModelNode model, ModelNode listAttribute) throws OperationFailedException { String value = VALUE.resolveModelAttribute(context, model).asString(); ModelNode indexNode = INDEX.resolveModelAttribute(context, model); LinkedList<ModelNode> res = new LinkedList<>( listAttribute.isDefined() ? listAttribute.asList() : Collections.<ModelNode>emptyList()); if (indexNode.isDefined()) { res.add(indexNode.asInt(), new ModelNode(value)); } else { res.add(new ModelNode(value)); } listAttribute.set(res); }
@Test public void testPropertyValueTypeExpressionConverter() throws Exception { ModelNode description = createDescription(ModelType.PROPERTY, ModelType.INT); TypeConverter converter = getConverter(description); ModelNode node = new ModelNode(); node.set("name", "${this.should.not.exist.!!!!!:1}"); node.protect(); ModelNode expected = node.clone().resolve(); Assert.assertEquals(SimpleType.STRING, converter.getOpenType()); String dmr = assertCast(String.class, converter.fromModelNode(node)); Assert.assertEquals(expected, ModelNode.fromString(dmr)); Assert.assertEquals(dmr, assertCast(String.class, converter.fromModelNode(expected))); assertToArray(converter, dmr); }
/** * Finds a value in the given {@code operationObject} whose key matches this attribute's {@link * #getName() name} and validates it using this attribute's {@link #getValidator() validator}. * * @param operationObject model node of type {@link ModelType#OBJECT}, typically representing an * operation request * @return the value * @throws OperationFailedException if the value is not valid */ public ModelNode validateOperation(final ModelNode operationObject) throws OperationFailedException { ModelNode node = new ModelNode(); if (operationObject.has(name)) { node.set(operationObject.get(name)); } if (isAllowExpression() && node.getType() == ModelType.STRING) { node = ParseUtils.parsePossibleExpression(node.asString()); } if (!node.isDefined() && defaultValue.isDefined()) { validator.validateParameter(name, defaultValue); } else { validator.validateParameter(name, node); } return node; }
private static void checkSensitiveAttribute(ManagementInterface client, boolean expectSuccess) throws IOException { ModelNode correct = new ModelNode(); if (expectSuccess) { correct.set("sa"); } ModelNode attrValue = readResource(client, EXAMPLE_DS, Outcome.SUCCESS).get(RESULT, PASSWORD); assertEquals(correct, attrValue); attrValue = readAttribute( client, EXAMPLE_DS, PASSWORD, expectSuccess ? Outcome.SUCCESS : Outcome.UNAUTHORIZED) .get(RESULT); assertEquals(correct, attrValue); }
protected void checkSensitiveAttribute( ModelControllerClient client, String host, String server, boolean expectSuccess, String... roles) throws IOException { String dsAddress = host == null ? DEFAULT_PROFILE + "/" + EXAMPLE_DS : "host=" + host + "server=" + server + "/" + EXAMPLE_DS; ModelNode attrValue = readResource(client, dsAddress, host, server, Outcome.SUCCESS, roles).get(RESULT, PASSWORD); ModelNode correct = new ModelNode(); if (expectSuccess) { correct.set("sa"); } assertEquals(correct, attrValue); }
public static ModelNode parseAttributeValue( final String value, final boolean isExpressionAllowed, final ModelType attributeType) { final String trimmed = value == null ? null : value.trim(); ModelNode node; if (trimmed != null) { if (isExpressionAllowed && isExpression(trimmed)) { node = new ModelNode(new ValueExpression(trimmed)); } else { if (attributeType == STRING || attributeType == PROPERTY) { node = new ModelNode().set(value); } else { node = new ModelNode().set(trimmed); } } if (node.getType() != ModelType.EXPRESSION) { // Convert the string to the expected type switch (attributeType) { case BIG_DECIMAL: node.set(node.asBigDecimal()); break; case BIG_INTEGER: node.set(node.asBigInteger()); break; case BOOLEAN: node.set(node.asBoolean()); break; case BYTES: node.set(node.asBytes()); break; case DOUBLE: node.set(node.asDouble()); break; case INT: node.set(node.asInt()); break; case LONG: node.set(node.asLong()); break; } } } else { node = new ModelNode(); } return node; }
private void addManagementConnections(List<ModelNode> updates) { if (hostModel.get(CORE_SERVICE, MANAGEMENT, LDAP_CONNECTION).isDefined()) { ModelNode baseAddress = new ModelNode(); baseAddress.add(CORE_SERVICE, MANAGEMENT); ModelNode connections = hostModel.get(CORE_SERVICE, MANAGEMENT, LDAP_CONNECTION); for (String connectionName : connections.keys()) { ModelNode addConnection = new ModelNode(); // First take the properties to pass over. addConnection.set(connections.get(connectionName)); // Now convert it to an operation by adding a name and address. ModelNode identityAddress = baseAddress.clone().add(LDAP_CONNECTION, connectionName); addConnection.get(OP).set(ADD); addConnection.get(OP_ADDR).set(identityAddress); updates.add(addConnection); } } }
@Override public ModelNode getOperationDescription(CommandContext ctx) throws CommandLineException { ModelNode request = initRequest(ctx); if (request == null) { return null; } request.get(Util.OPERATION).set(Util.READ_OPERATION_DESCRIPTION); request.get(Util.NAME).set(Util.ADD); final ModelNode response; try { response = ctx.getModelControllerClient().execute(request); } catch (IOException e) { throw new CommandFormatException("Failed to execute read-operation-description.", e); } if (!response.hasDefined(Util.RESULT)) { return null; } final ModelNode result = response.get(Util.RESULT); final ModelNode opDescr = result.get(Util.DESCRIPTION); final StringBuilder buf = new StringBuilder(); buf.append(opDescr.asString()); buf.append(" (unlike the add operation, this command accepts xa-datasource-properties)."); opDescr.set(buf.toString()); final ModelNode allProps = result.get(Util.REQUEST_PROPERTIES); final ModelNode conProps = allProps.get(CONNECTION_PROPERTIES); conProps .get(Util.DESCRIPTION) .set( "A comma-separated list of datasource connection properties in key=value pair format."); conProps.get(Util.TYPE).set(ModelType.LIST); conProps.get(Util.REQUIRED).set(false); conProps.get(Util.NILLABLE).set(false); return result; }
/** For WFCORE-1590 scenarios */ @Test public void testMinMaxSize() { ModelNode toValidate = new ModelNode(); ModelNode paramVal = toValidate.get("test"); // Test that explicitly configured validator controls. // This isn't some sort of ideal behavior, so if we can make setMin/MaxSize take precedence // that's fine and this part of the test can be changed. This is more a sanity check // that the current code is doing what's expected. SimpleAttributeDefinition ad = new SimpleAttributeDefinitionBuilder("test", ModelType.STRING) .setValidator(new StringLengthValidator(2, 3, false, false)) .setMinSize(1) .setMaxSize(4) .build(); paramVal.set("a"); validate(ad, toValidate, true); paramVal.set("ab"); validate(ad, toValidate, false); paramVal.set("abc"); validate(ad, toValidate, false); paramVal.set("abcd"); validate(ad, toValidate, true); // Test that setMin/MaxSize control in the absence of explicit validation ad = new SimpleAttributeDefinitionBuilder("test", ModelType.STRING) .setMinSize(2) .setMaxSize(3) .build(); paramVal.set("a"); validate(ad, toValidate, true); paramVal.set("ab"); validate(ad, toValidate, false); paramVal.set("abc"); validate(ad, toValidate, false); paramVal.set("abcd"); validate(ad, toValidate, true); // Test that default min is 1 ad = new SimpleAttributeDefinitionBuilder("test", ModelType.STRING).setMaxSize(3).build(); paramVal.set(""); validate(ad, toValidate, true); paramVal.set("a"); validate(ad, toValidate, false); paramVal.set("ab"); validate(ad, toValidate, false); paramVal.set("abc"); validate(ad, toValidate, false); paramVal.set("abcd"); validate(ad, toValidate, true); // Test that default max is big ad = new SimpleAttributeDefinitionBuilder("test", ModelType.STRING).build(); paramVal.set(""); validate(ad, toValidate, true); paramVal.set( "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz" + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz" + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); validate(ad, toValidate, false); }
@Override void execute(final ModelNode operation, final SocketBinding binding, final ModelNode result) { // The socket should be bound when it's registered at the SocketBindingManager result.set(binding.isBound()); }
@Override public void execute(OperationContext context, ModelNode operation) throws OperationFailedException { ModelNode operationModel = new ModelNode(); populateModel(operation, operationModel); String attributeName = NAME.resolveModelAttribute(context, operationModel).asString(); final ImmutableManagementResourceRegistration registry = context.getResourceRegistration(); final boolean useEnhancedSyntax = containsEnhancedSyntax(attributeName, registry); String attributeExpression = attributeName; if (useEnhancedSyntax) { attributeName = extractAttributeName(attributeName); } final AttributeAccess attributeAccess = context .getResourceRegistration() .getAttributeAccess(PathAddress.EMPTY_ADDRESS, attributeName); if (attributeAccess == null) { throw new OperationFailedException( ControllerLogger.ROOT_LOGGER.unknownAttribute(attributeName)); } final PathAddress address = PathAddress.pathAddress(operation.get(OP_ADDR)); final ModelNode readResponse = new ModelNode(); // prepare write operation ModelNode writeOperation = Util.createOperation(WriteAttributeHandler.DEFINITION, address); writeOperation.get(NAME.getName()).set(useEnhancedSyntax ? attributeExpression : attributeName); ModelNode writeOperationValue = writeOperation.get( ModelDescriptionConstants.VALUE); // value will be set in modification step if (attributeAccess.getStorageType() == AttributeAccess.Storage.CONFIGURATION) { // Steps need to be performed before any other steps, so they are added in opposite order // with addFirst=true parameter. // 2. modify value and register writing step context.addStep( (context1, operation1) -> { updateModel( context, operationModel, attributeAccess.getAttributeDefinition(), readResponse.get(RESULT)); // add write step if (requiredReadWriteAccess) { writeOperationValue.set(readResponse.get(RESULT)); context.addStep( writeOperation, WriteAttributeHandler.INSTANCE, OperationContext.Stage.MODEL, true); } }, OperationContext.Stage.MODEL, true); // 1. read current attribute value ModelNode readAttributeOperation = Util.getReadAttributeOperation( address, useEnhancedSyntax ? attributeExpression : attributeName); context.addStep( readResponse, readAttributeOperation, ReadAttributeHandler.INSTANCE, OperationContext.Stage.MODEL, true); } else { assert attributeAccess.getStorageType() == AttributeAccess.Storage.RUNTIME; // For Storage.RUNTIME attributes, attributes need to be registered with reader and writer // step handlers, // which must postpone reading / writing to RUNTIME stage (by registering new RUNTIME steps // which will // perform actual reading / writing). // Steps need to be performed before any other steps, so they are added in opposite order // with addFirst=true parameter. // 3. write modified value if (requiredReadWriteAccess) { context.addStep( readResponse, writeOperation, WriteAttributeHandler.INSTANCE, OperationContext.Stage.MODEL, true); } // 2. modify value context.addStep( (context1, operation1) -> { context.addStep( (context2, operation2) -> { updateModel( context2, operationModel, attributeAccess.getAttributeDefinition(), readResponse.get(RESULT)); writeOperationValue.set(readResponse.get(RESULT)); }, OperationContext.Stage.RUNTIME); }, OperationContext.Stage.MODEL, true); // 1. read current attribute value ModelNode readAttributeOperation = Util.getReadAttributeOperation( address, useEnhancedSyntax ? attributeExpression : attributeName); context.addStep( readResponse, readAttributeOperation, ReadAttributeHandler.INSTANCE, OperationContext.Stage.MODEL, true); } }