/* * 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.controller.resource; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ALTERNATIVES; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.INTERFACE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.VALUE_TYPE; import java.util.Arrays; import java.util.HashSet; import java.util.Locale; import java.util.ResourceBundle; import java.util.Set; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import org.jboss.as.controller.AttributeDefinition; import org.jboss.as.controller.AttributeMarshaller; import org.jboss.as.controller.ListAttributeDefinition; import org.jboss.as.controller.OperationFailedException; import org.jboss.as.controller.ParameterCorrector; import org.jboss.as.controller.PathElement; import org.jboss.as.controller.ReadResourceNameOperationStepHandler; import org.jboss.as.controller.SimpleAttributeDefinitionBuilder; import org.jboss.as.controller.SimpleListAttributeDefinition; import org.jboss.as.controller.SimpleResourceDefinition; import org.jboss.as.controller.access.management.SensitiveTargetAccessConstraintDefinition; import org.jboss.as.controller.client.helpers.MeasurementUnit; import org.jboss.as.controller.descriptions.ModelDescriptionConstants; import org.jboss.as.controller.descriptions.ResourceDescriptionResolver; import org.jboss.as.controller.descriptions.common.ControllerResolver; import org.jboss.as.controller.logging.ControllerLogger; import org.jboss.as.controller.operations.common.InterfaceAddHandler; import org.jboss.as.controller.operations.common.InterfaceCriteriaWriteHandler; import org.jboss.as.controller.operations.common.InterfaceRemoveHandler; import org.jboss.as.controller.operations.validation.ModelTypeValidator; import org.jboss.as.controller.operations.validation.ParameterValidator; import org.jboss.as.controller.parsing.Element; import org.jboss.as.controller.registry.AttributeAccess; import org.jboss.as.controller.registry.ManagementResourceRegistration; import org.jboss.dmr.ModelNode; import org.jboss.dmr.ModelType; /** * @author <a href="mailto:tomaz.cerar@redhat.com">Tomaz Cerar</a> (c) 2012 Red Hat Inc. */ public class InterfaceDefinition extends SimpleResourceDefinition { public static final String INTERFACE_CAPABILITY_NAME = "org.wildfly.network.interface"; public static final String[] OTHERS = new String[]{localName(Element.INET_ADDRESS), localName(Element.LINK_LOCAL_ADDRESS), localName(Element.LOOPBACK), localName(Element.LOOPBACK_ADDRESS), localName(Element.MULTICAST), localName(Element.NIC), localName(Element.NIC_MATCH), localName(Element.POINT_TO_POINT), localName(Element.PUBLIC_ADDRESS), localName(Element.SITE_LOCAL_ADDRESS), localName(Element.SUBNET_MATCH), localName(Element.UP), localName(Element.VIRTUAL), localName(Element.ANY), localName(Element.NOT) }; public static final AttributeDefinition NAME = SimpleAttributeDefinitionBuilder.create(ModelDescriptionConstants.NAME, ModelType.STRING) .setResourceOnly() .build(); public static final AttributeDefinition ANY_ADDRESS = SimpleAttributeDefinitionBuilder.create(ModelDescriptionConstants.ANY_ADDRESS, ModelType.BOOLEAN) .setAllowExpression(false).setAllowNull(true).setRestartAllServices() .setValidator(new ModelTypeValidator(ModelType.BOOLEAN, true, false)) .addAlternatives(OTHERS) .build(); /** * All other attribute names. */ public static final AttributeDefinition INET_ADDRESS = SimpleAttributeDefinitionBuilder.create(ModelDescriptionConstants.INET_ADDRESS, ModelType.STRING) .setAllowExpression(true).setAllowNull(true).addAlternatives(ModelDescriptionConstants.ANY_ADDRESS).setRestartAllServices() .build(); public static final AttributeDefinition LINK_LOCAL_ADDRESS = SimpleAttributeDefinitionBuilder.create(localName(Element.LINK_LOCAL_ADDRESS), ModelType.BOOLEAN) .setAllowExpression(false).setAllowNull(true).addAlternatives(ModelDescriptionConstants.ANY_ADDRESS).setRestartAllServices() .build(); public static final AttributeDefinition LOOPBACK = SimpleAttributeDefinitionBuilder.create(localName(Element.LOOPBACK), ModelType.BOOLEAN) .setAllowExpression(false).setAllowNull(true).addAlternatives(ModelDescriptionConstants.ANY_ADDRESS).setRestartAllServices() .build(); public static final AttributeDefinition LOOPBACK_ADDRESS = SimpleAttributeDefinitionBuilder.create(localName(Element.LOOPBACK_ADDRESS), ModelType.STRING) .setAllowExpression(true).setAllowNull(true).addAlternatives(ModelDescriptionConstants.ANY_ADDRESS).setRestartAllServices() .build(); public static final AttributeDefinition NIC = SimpleAttributeDefinitionBuilder.create(localName(Element.NIC), ModelType.STRING) .setAllowExpression(true).setAllowNull(true).addAlternatives(ModelDescriptionConstants.ANY_ADDRESS).setRestartAllServices() .build(); public static final AttributeDefinition NIC_MATCH = SimpleAttributeDefinitionBuilder.create(localName(Element.NIC_MATCH), ModelType.STRING) .setAllowExpression(true).setAllowNull(true).addAlternatives(ModelDescriptionConstants.ANY_ADDRESS).setRestartAllServices() .build(); public static final AttributeDefinition MULTICAST = SimpleAttributeDefinitionBuilder.create(localName(Element.MULTICAST), ModelType.BOOLEAN) .setAllowExpression(false).setAllowNull(true).addAlternatives(ModelDescriptionConstants.ANY_ADDRESS).setRestartAllServices() .build(); public static final AttributeDefinition POINT_TO_POINT = SimpleAttributeDefinitionBuilder.create(localName(Element.POINT_TO_POINT), ModelType.BOOLEAN) .setAllowExpression(false).setAllowNull(true).addAlternatives(ModelDescriptionConstants.ANY_ADDRESS).setRestartAllServices() .build(); public static final AttributeDefinition PUBLIC_ADDRESS = SimpleAttributeDefinitionBuilder.create(localName(Element.PUBLIC_ADDRESS), ModelType.BOOLEAN) .setAllowExpression(false).setAllowNull(true).addAlternatives(ModelDescriptionConstants.ANY_ADDRESS).setRestartAllServices() .build(); public static final AttributeDefinition SITE_LOCAL_ADDRESS = SimpleAttributeDefinitionBuilder.create(localName(Element.SITE_LOCAL_ADDRESS), ModelType.BOOLEAN) .setAllowExpression(false).setAllowNull(true).addAlternatives(ModelDescriptionConstants.ANY_ADDRESS).setRestartAllServices() .build(); public static final AttributeDefinition SUBNET_MATCH = SimpleAttributeDefinitionBuilder.create(localName(Element.SUBNET_MATCH), ModelType.STRING) .setAllowExpression(true).setAllowNull(true).addAlternatives(ModelDescriptionConstants.ANY_ADDRESS).setRestartAllServices() .build(); public static final AttributeDefinition UP = SimpleAttributeDefinitionBuilder.create(localName(Element.UP), ModelType.BOOLEAN) .setAllowExpression(false).setAllowNull(true).addAlternatives(ModelDescriptionConstants.ANY_ADDRESS).setRestartAllServices() .build(); /** * The any-* alternatives. */ public static final AttributeDefinition VIRTUAL = SimpleAttributeDefinitionBuilder.create(localName(Element.VIRTUAL), ModelType.BOOLEAN) .setAllowExpression(false).setAllowNull(true).addAlternatives(ModelDescriptionConstants.ANY_ADDRESS).setRestartAllServices() .build(); public static final AttributeDefinition[] NESTED_ATTRIBUTES = new AttributeDefinition[]{ INET_ADDRESS, LINK_LOCAL_ADDRESS, LOOPBACK, LOOPBACK_ADDRESS, MULTICAST, NIC, NIC_MATCH, POINT_TO_POINT, PUBLIC_ADDRESS, SITE_LOCAL_ADDRESS, SUBNET_MATCH, UP, VIRTUAL }; public static final AttributeDefinition NOT = createNestedComplexType("not"); public static final AttributeDefinition ANY = createNestedComplexType("any"); /*public static final ObjectTypeAttributeDefinition NOT = new ObjectTypeAttributeDefinition.Builder("not", NESTED_ATTRIBUTES) .setAllowNull(true) .build(); public static final ObjectTypeAttributeDefinition ANY = new ObjectTypeAttributeDefinition.Builder("any", NESTED_ATTRIBUTES) .setAllowNull(true) .build();*/ /** * The root attributes. */ public static final AttributeDefinition[] ROOT_ATTRIBUTES = new AttributeDefinition[]{ ANY_ADDRESS, INET_ADDRESS, LINK_LOCAL_ADDRESS, LOOPBACK, LOOPBACK_ADDRESS, MULTICAST, NIC, NIC_MATCH, POINT_TO_POINT, PUBLIC_ADDRESS, SITE_LOCAL_ADDRESS, SUBNET_MATCH, UP, VIRTUAL, ANY, NOT }; /** * The nested attributes for any, not. */ public static final Set<AttributeDefinition> NESTED_LIST_ATTRIBUTES = new HashSet<AttributeDefinition>( Arrays.asList(INET_ADDRESS, NIC, NIC_MATCH, SUBNET_MATCH) ); /** * The wildcard criteria attributes */ /*public static final AttributeDefinition[] WILDCARD_ATTRIBUTES = new AttributeDefinition[]{ANY_ADDRESS, ANY_IPV4_ADDRESS, ANY_IPV6_ADDRESS}; public static final AttributeDefinition[] SIMPLE_ATTRIBUTES = new AttributeDefinition[]{LINK_LOCAL_ADDRESS, LOOPBACK, MULTICAST, POINT_TO_POINT, PUBLIC_ADDRESS, SITE_LOCAL_ADDRESS, UP, VIRTUAL};*/ private final boolean updateRuntime; private final boolean resolvable; public InterfaceDefinition(InterfaceAddHandler addHandler, InterfaceRemoveHandler removeHandler, boolean updateRuntime, boolean resolvable) { super(new Parameters(PathElement.pathElement(INTERFACE), ControllerResolver.getResolver(INTERFACE)) .setAddHandler(addHandler) .setRemoveHandler(removeHandler) .setAccessConstraints(SensitiveTargetAccessConstraintDefinition.SOCKET_CONFIG)); this.updateRuntime = updateRuntime; this.resolvable = resolvable; } public static String localName(final Element element) { return element.getLocalName(); } /** * Test whether the operation has a defined criteria attribute. * * @param operation the operation * @return */ public static boolean isOperationDefined(final ModelNode operation) { for (final AttributeDefinition def : ROOT_ATTRIBUTES) { if (operation.hasDefined(def.getName())) { return true; } } return false; } @Override public void registerOperations(ManagementResourceRegistration interfaces) { super.registerOperations(interfaces); if(resolvable) { interfaces.registerOperationHandler(org.jboss.as.controller.operations.global.ReadResourceHandler.RESOLVE_DEFINITION, org.jboss.as.controller.operations.global.ReadResourceHandler.RESOLVE_INSTANCE, true); interfaces.registerOperationHandler(org.jboss.as.controller.operations.global.ReadAttributeHandler.RESOLVE_DEFINITION, org.jboss.as.controller.operations.global.ReadAttributeHandler.RESOLVE_INSTANCE, true); interfaces.registerOperationHandler(org.jboss.as.controller.operations.global.ReadAttributeGroupHandler.RESOLVE_DEFINITION, org.jboss.as.controller.operations.global.ReadAttributeGroupHandler.RESOLVE_INSTANCE, true); } } @Override public void registerAttributes(ManagementResourceRegistration registration) { super.registerAttributes(registration); InterfaceCriteriaWriteHandler handler = updateRuntime ? InterfaceCriteriaWriteHandler.UPDATE_RUNTIME : InterfaceCriteriaWriteHandler.CONFIG_ONLY; for (final AttributeDefinition def : InterfaceDefinition.ROOT_ATTRIBUTES) { registration.registerReadWriteAttribute(def, null, handler); } registration.registerReadOnlyAttribute(InterfaceDefinition.NAME, ReadResourceNameOperationStepHandler.INSTANCE); } @Deprecated private static AttributeDefinition createNestedComplexType(final String name) { return new AttributeDefinition(name, name, null, ModelType.OBJECT, true, false, MeasurementUnit.NONE, (ParameterCorrector) null, createNestedParamValidator(), true, new String[]{ModelDescriptionConstants.ANY_ADDRESS}, (String[]) null, (AttributeMarshaller) null, false, null, null, (Boolean) null, null, AttributeAccess.Flag.RESTART_ALL_SERVICES) { @Override public ModelNode addResourceAttributeDescription(final ResourceBundle bundle, final String prefix, final ModelNode resourceDescription) { final ModelNode result = super.addResourceAttributeDescription(bundle, prefix, resourceDescription); addNestedDescriptions(result, prefix, bundle); return result; } @Override public ModelNode addOperationParameterDescription(ResourceBundle bundle, String prefix, ModelNode operationDescription) { final ModelNode result = super.addOperationParameterDescription(bundle, prefix, operationDescription); addNestedDescriptions(result, prefix, bundle); return result; } @Override public ModelNode addResourceAttributeDescription(ModelNode resourceDescription, ResourceDescriptionResolver resolver, Locale locale, ResourceBundle bundle) { ModelNode result = super.addResourceAttributeDescription(resourceDescription, resolver, locale, bundle); for (final AttributeDefinition def : NESTED_ATTRIBUTES) { result.get(VALUE_TYPE, def.getName(), ModelDescriptionConstants.DESCRIPTION).set(resolver.getResourceAttributeDescription(def.getName(), locale, bundle)); } return result; } @Override public ModelNode addOperationParameterDescription(ModelNode resourceDescription, String operationName, ResourceDescriptionResolver resolver, Locale locale, ResourceBundle bundle) { ModelNode result = super.addOperationParameterDescription(resourceDescription, operationName, resolver, locale, bundle); for (final AttributeDefinition def : NESTED_ATTRIBUTES) { result.get(VALUE_TYPE, def.getName(), ModelDescriptionConstants.DESCRIPTION).set(resolver.getOperationParameterDescription(operationName, def.getName(), locale, bundle)); } return result; } void addNestedDescriptions(final ModelNode result, final String prefix, final ResourceBundle bundle) { for (final AttributeDefinition def : NESTED_ATTRIBUTES) { final String bundleKey = prefix == null ? def.getName() : (prefix + "." + def.getName()); result.get(VALUE_TYPE, def.getName(), ModelDescriptionConstants.DESCRIPTION).set(bundle.getString(bundleKey)); } } @Override public ModelNode getNoTextDescription(boolean forOperation) { final ModelNode model = super.getNoTextDescription(forOperation); final ModelNode valueType = model.get(VALUE_TYPE); for (final AttributeDefinition def : NESTED_ATTRIBUTES) { final AttributeDefinition current; if (NESTED_LIST_ATTRIBUTES.contains(def)) { current = wrapAsList(def); } else { current = def; } final ModelNode m = current.getNoTextDescription(forOperation); m.remove(ALTERNATIVES); valueType.get(current.getName()).set(m); } return model; } }; } /** * Wrap a simple attribute def as list. * * @param def the attribute definition * @return the list attribute def */ @Deprecated private static ListAttributeDefinition wrapAsList(final AttributeDefinition def) { final ListAttributeDefinition list = new ListAttributeDefinition(new SimpleListAttributeDefinition.Builder(def.getName(), def) .setElementValidator(def.getValidator())) { @Override public ModelNode getNoTextDescription(boolean forOperation) { final ModelNode model = super.getNoTextDescription(forOperation); setValueType(model); return model; } @Override protected void addValueTypeDescription(final ModelNode node, final ResourceBundle bundle) { setValueType(node); } @Override public void marshallAsElement(final ModelNode resourceModel, final boolean marshalDefault, final XMLStreamWriter writer) throws XMLStreamException { throw new RuntimeException(); } @Override protected void addAttributeValueTypeDescription(ModelNode node, ResourceDescriptionResolver resolver, Locale locale, ResourceBundle bundle) { setValueType(node); } @Override protected void addOperationParameterValueTypeDescription(ModelNode node, String operationName, ResourceDescriptionResolver resolver, Locale locale, ResourceBundle bundle) { setValueType(node); } private void setValueType(ModelNode node) { node.get(ModelDescriptionConstants.VALUE_TYPE).set(ModelType.STRING); } }; return list; } @Deprecated static ParameterValidator createNestedParamValidator() { return new ModelTypeValidator(ModelType.OBJECT, true, false, true) { @Override public void validateParameter(final String parameterName, final ModelNode value) throws OperationFailedException { super.validateParameter(parameterName, value); for (final AttributeDefinition def : NESTED_ATTRIBUTES) { final String name = def.getName(); if (value.hasDefined(name)) { final ModelNode v = value.get(name); if (NESTED_LIST_ATTRIBUTES.contains(def)) { if (ModelType.LIST != v.getType()) { throw new OperationFailedException(ControllerLogger.ROOT_LOGGER.invalidType(v.getType())); } } else { def.getValidator().validateParameter(name, v); } } } } }; } }