/* * JBoss, Home of Professional Open Source. * Copyright 2011, 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.host.controller.parsing; import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CORE_SERVICE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DIRECTORY_GROUPING; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DISCOVERY_OPTION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DISCOVERY_OPTIONS; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DOMAIN_CONTROLLER; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.HOST; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.HTTP_INTERFACE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.HTTP_UPGRADE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.IGNORED_RESOURCES; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.IGNORED_RESOURCE_TYPE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.LOCAL; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.LOOPBACK; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.MANAGEMENT_INTERFACE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.NAME; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.NATIVE_INTERFACE; 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.ORGANIZATION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PROPERTIES; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REMOTE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SERVER_CONFIG; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SOCKET_BINDING_GROUP; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SSL; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.STATIC_DISCOVERY; import static org.jboss.as.controller.parsing.ParseUtils.isNoNamespaceAttribute; import static org.jboss.as.controller.parsing.ParseUtils.missingOneOf; import static org.jboss.as.controller.parsing.ParseUtils.missingRequired; import static org.jboss.as.controller.parsing.ParseUtils.missingRequiredElement; import static org.jboss.as.controller.parsing.ParseUtils.nextElement; import static org.jboss.as.controller.parsing.ParseUtils.requireNamespace; import static org.jboss.as.controller.parsing.ParseUtils.requireNoAttributes; import static org.jboss.as.controller.parsing.ParseUtils.requireNoContent; import static org.jboss.as.controller.parsing.ParseUtils.requireNoNamespaceAttribute; import static org.jboss.as.controller.parsing.ParseUtils.unexpectedAttribute; import static org.jboss.as.controller.parsing.ParseUtils.unexpectedElement; import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import javax.xml.stream.XMLStreamException; import org.jboss.as.controller.RunningMode; import org.jboss.as.controller.extension.ExtensionRegistry; import org.jboss.as.controller.logging.ControllerLogger; import org.jboss.as.controller.operations.common.Util; import org.jboss.as.controller.parsing.Attribute; import org.jboss.as.controller.parsing.Element; import org.jboss.as.controller.parsing.ExtensionXml; import org.jboss.as.controller.parsing.Namespace; import org.jboss.as.controller.parsing.ParseUtils; import org.jboss.as.controller.parsing.ProfileParsingCompletionHandler; import org.jboss.as.controller.persistence.ModelMarshallingContext; import org.jboss.as.controller.resource.AbstractSocketBindingGroupResourceDefinition; import org.jboss.as.domain.management.parsing.AuditLogXml; import org.jboss.as.domain.management.parsing.ManagementXml; import org.jboss.as.domain.management.parsing.ManagementXmlDelegate; import org.jboss.as.host.controller.discovery.DiscoveryOptionResourceDefinition; import org.jboss.as.host.controller.discovery.StaticDiscoveryResourceDefinition; import org.jboss.as.host.controller.ignored.IgnoredDomainTypeResourceDefinition; import org.jboss.as.host.controller.logging.HostControllerLogger; import org.jboss.as.host.controller.model.host.AdminOnlyDomainConfigPolicy; import org.jboss.as.host.controller.model.host.HostResourceDefinition; import org.jboss.as.host.controller.operations.DomainControllerWriteAttributeHandler; import org.jboss.as.host.controller.operations.HostModelRegistrationHandler; import org.jboss.as.host.controller.resources.HttpManagementResourceDefinition; import org.jboss.as.host.controller.resources.NativeManagementResourceDefinition; import org.jboss.as.host.controller.resources.ServerConfigResourceDefinition; import org.jboss.as.host.controller.resources.SslLoopbackResourceDefinition; import org.jboss.as.process.CommandLineConstants; import org.jboss.as.server.parsing.CommonXml; import org.jboss.as.server.parsing.SocketBindingsXml; import org.jboss.as.server.services.net.SocketBindingGroupResourceDefinition; import org.jboss.dmr.ModelNode; import org.jboss.dmr.ModelType; import org.jboss.dmr.Property; import org.jboss.staxmapper.XMLExtendedStreamReader; import org.jboss.staxmapper.XMLExtendedStreamWriter; /** * A mapper between an AS server's configuration model and XML representations, particularly {@code host.xml} * * @author Brian Stansberry * @author <a href="mailto:darran.lofthouse@jboss.com">Darran Lofthouse</a> * @author <a href="mailto:jperkins@jboss.com">James R. Perkins</a> */ class HostXml_4 extends CommonXml implements ManagementXmlDelegate { private final AuditLogXml auditLogDelegate; private final String defaultHostControllerName; private final RunningMode runningMode; private final boolean isCachedDc; private final ExtensionRegistry extensionRegistry; private final ExtensionXml extensionXml; private final Namespace namespace; HostXml_4(String defaultHostControllerName, RunningMode runningMode, boolean isCachedDC, final ExtensionRegistry extensionRegistry, final ExtensionXml extensionXml, final Namespace namespace) { super(new SocketBindingsXml.HostSocketBindingsXml()); this.auditLogDelegate = AuditLogXml.newInstance(namespace, true); this.defaultHostControllerName = defaultHostControllerName; this.runningMode = runningMode; this.isCachedDc = isCachedDC; this.extensionRegistry = extensionRegistry; this.extensionXml = extensionXml; this.namespace = namespace; } @Override public void readElement(final XMLExtendedStreamReader reader, final List<ModelNode> operationList) throws XMLStreamException { final ModelNode address = new ModelNode().setEmptyList(); if (Element.forName(reader.getLocalName()) != Element.HOST) { throw unexpectedElement(reader); } // Instead of having to list the remaining versions we just check it is actually a valid version. for (Namespace current : Namespace.domainValues()) { if (namespace.equals(current)) { readHostElement(reader, address, operationList); return; } } throw unexpectedElement(reader); } @Override public void writeContent(final XMLExtendedStreamWriter writer, final ModelMarshallingContext context) throws XMLStreamException { throw new UnsupportedOperationException(); } private void readHostElement(final XMLExtendedStreamReader reader, final ModelNode address, final List<ModelNode> list) throws XMLStreamException { String hostName = null; String organization = null; // Deffer adding the namespaces and schema locations until after the host has been created. List<ModelNode> namespaceOperations = new LinkedList<ModelNode>(); parseNamespaces(reader, address, namespaceOperations); // attributes final int count = reader.getAttributeCount(); for (int i = 0; i < count; i++) { switch (Namespace.forUri(reader.getAttributeNamespace(i))) { case NONE: { final String value = reader.getAttributeValue(i); final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); switch (attribute) { case NAME: { hostName = value; break; } case ORGANIZATION : { organization = value; break; } default: throw unexpectedAttribute(reader, i); } break; } case XML_SCHEMA_INSTANCE: { switch (Attribute.forName(reader.getAttributeLocalName(i))) { case SCHEMA_LOCATION: { parseSchemaLocations(reader, address, namespaceOperations, i); break; } case NO_NAMESPACE_SCHEMA_LOCATION: { // todo, jeez break; } default: { throw unexpectedAttribute(reader, i); } } break; } default: throw unexpectedAttribute(reader, i); } } // The following also updates the address parameter so this address can be used for future operations // in the context of this host. addLocalHost(address, list, hostName); setOrganization(address, list, organization); // The namespace operations were created before the host name was known, the address can now be updated // to the local host specific address. for (ModelNode operation : namespaceOperations) { operation.get(OP_ADDR).set(address); list.add(operation); } // Content // Handle elements: sequence Element element = nextElement(reader, namespace); if (element == Element.EXTENSIONS) { extensionXml.parseExtensions(reader, address, namespace, list); element = nextElement(reader, namespace); } if (element == Element.SYSTEM_PROPERTIES) { parseSystemProperties(reader, address, namespace, list, false); element = nextElement(reader, namespace); } if (element == Element.PATHS) { parsePaths(reader, address, namespace, list, true); element = nextElement(reader, namespace); } if (element == Element.VAULT) { parseVault(reader, address, namespace, list); element = nextElement(reader, namespace); } if (element == Element.MANAGEMENT) { ManagementXml managementXml = ManagementXml.newInstance(namespace, this); managementXml.parseManagement(reader, address, list, true); element = nextElement(reader, namespace); } else { throw missingRequiredElement(reader, EnumSet.of(Element.MANAGEMENT)); } if (element == Element.DOMAIN_CONTROLLER) { parseDomainController(reader, address, list); element = nextElement(reader, namespace); } final Set<String> interfaceNames = new HashSet<String>(); if (element == Element.INTERFACES) { parseInterfaces(reader, interfaceNames, address, namespace, list, true); element = nextElement(reader, namespace); } if (element == Element.JVMS) { parseJvms(reader, address, list); element = nextElement(reader, namespace); } if (element == Element.SERVERS) { parseServers(reader, address, list); element = nextElement(reader, namespace); } if (element == Element.PROFILE) { parseHostProfile(reader, address, list); element = nextElement(reader, namespace); } // Single socket binding group if (element == Element.SOCKET_BINDING_GROUP) { parseSocketBindingGroup(reader, interfaceNames, address, list); element = nextElement(reader, namespace); } if (element != null) { throw unexpectedElement(reader); } } private void parseHttpManagementInterfaceAttributes(XMLExtendedStreamReader reader, ModelNode addOp) throws XMLStreamException { final int count = reader.getAttributeCount(); for (int i = 0; i < count; i++) { final String value = reader.getAttributeValue(i); if (!isNoNamespaceAttribute(reader, i)) { throw unexpectedAttribute(reader, i); } else { final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); switch (attribute) { case SASL_PROTOCOL: { HttpManagementResourceDefinition.SASL_PROTOCOL.parseAndSetParameter(value, addOp, reader); break; } case SECURITY_REALM: { HttpManagementResourceDefinition.SECURITY_REALM.parseAndSetParameter(value, addOp, reader); break; } case SERVER_NAME: { NativeManagementResourceDefinition.SERVER_NAME.parseAndSetParameter(value, addOp, reader); break; } case CONSOLE_ENABLED: { HttpManagementResourceDefinition.CONSOLE_ENABLED.parseAndSetParameter(value, addOp, reader); break; } case HTTP_UPGRADE_ENABLED: { ModelNode httpUpgrade = addOp.get(HTTP_UPGRADE); HttpManagementResourceDefinition.ENABLED.parseAndSetParameter(value, httpUpgrade, reader); break; } case ALLOWED_ORIGINS: { for (String origin : reader.getListAttributeValue(i)) { HttpManagementResourceDefinition.ALLOWED_ORIGINS.parseAndAddParameterElement(origin, addOp, reader); } break; } default: throw unexpectedAttribute(reader, i); } } } } private void parseNativeManagementInterfaceAttributes(XMLExtendedStreamReader reader, ModelNode addOp) throws XMLStreamException { final int count = reader.getAttributeCount(); for (int i = 0; i < count; i++) { final String value = reader.getAttributeValue(i); if (!isNoNamespaceAttribute(reader, i)) { throw unexpectedAttribute(reader, i); } else { final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); switch (attribute) { case SASL_PROTOCOL: { NativeManagementResourceDefinition.SASL_PROTOCOL.parseAndSetParameter(value, addOp, reader); break; } case SECURITY_REALM: { NativeManagementResourceDefinition.SECURITY_REALM.parseAndSetParameter(value, addOp, reader); break; } case SERVER_NAME: { NativeManagementResourceDefinition.SERVER_NAME.parseAndSetParameter(value, addOp, reader); break; } default: throw unexpectedAttribute(reader, i); } } } } private void parseManagementInterface(XMLExtendedStreamReader reader, ModelNode address, boolean http, List<ModelNode> list) throws XMLStreamException { final ModelNode operationAddress = address.clone(); operationAddress.add(MANAGEMENT_INTERFACE, http ? HTTP_INTERFACE : NATIVE_INTERFACE); final ModelNode addOp = Util.getEmptyOperation(ADD, operationAddress); // Handle attributes if (http) { parseHttpManagementInterfaceAttributes(reader, addOp); } else { parseNativeManagementInterfaceAttributes(reader, addOp); } // Handle elements while (reader.hasNext() && reader.nextTag() != END_ELEMENT) { requireNamespace(reader, namespace); final Element element = Element.forName(reader.getLocalName()); switch (element) { case SOCKET: if (http) { parseHttpManagementSocket(reader, addOp); } else { parseNativeManagementSocket(reader, addOp); } break; default: throw unexpectedElement(reader); } } list.add(addOp); } private void parseNativeManagementSocket(XMLExtendedStreamReader reader, ModelNode addOp) throws XMLStreamException { // Handle attributes boolean hasInterface = false; final int count = reader.getAttributeCount(); for (int i = 0; i < count; i++) { final String value = reader.getAttributeValue(i); if (!isNoNamespaceAttribute(reader, i)) { throw unexpectedAttribute(reader, i); } else { final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); switch (attribute) { case INTERFACE: { NativeManagementResourceDefinition.INTERFACE.parseAndSetParameter(value, addOp, reader); hasInterface = true; break; } case PORT: { NativeManagementResourceDefinition.NATIVE_PORT.parseAndSetParameter(value, addOp, reader); break; } default: throw unexpectedAttribute(reader, i); } } } requireNoContent(reader); if (!hasInterface) { throw missingRequired(reader, Collections.singleton(Attribute.INTERFACE.getLocalName())); } } private void parseHttpManagementSocket(XMLExtendedStreamReader reader, ModelNode addOp) throws XMLStreamException { // Handle attributes boolean hasInterface = false; final int count = reader.getAttributeCount(); for (int i = 0; i < count; i++) { final String value = reader.getAttributeValue(i); if (!isNoNamespaceAttribute(reader, i)) { throw unexpectedAttribute(reader, i); } else { final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); switch (attribute) { case INTERFACE: { HttpManagementResourceDefinition.INTERFACE.parseAndSetParameter(value, addOp, reader); hasInterface = true; break; } case PORT: { HttpManagementResourceDefinition.HTTP_PORT.parseAndSetParameter(value, addOp, reader); break; } case SECURE_PORT: { HttpManagementResourceDefinition.HTTPS_PORT.parseAndSetParameter(value, addOp, reader); break; } case SECURE_INTERFACE: { HttpManagementResourceDefinition.SECURE_INTERFACE.parseAndSetParameter(value, addOp, reader); break; } default: throw unexpectedAttribute(reader, i); } } } requireNoContent(reader); if (!hasInterface) { throw missingRequired(reader, Collections.singleton(Attribute.INTERFACE.getLocalName())); } } private void setOrganization(final ModelNode address, final List<ModelNode> operationList, final String value) { if (value != null && !value.isEmpty()) { final ModelNode update = Util.getWriteAttributeOperation(address, ORGANIZATION, value); operationList.add(update); } } /** * Add the operation to add the local host definition. */ private void addLocalHost(final ModelNode address, final List<ModelNode> operationList, final String hostName) { String resolvedHost = hostName != null ? hostName : defaultHostControllerName; // All further operations should modify the newly added host so the address passed in is updated. address.add(HOST, resolvedHost); // Add a step to setup the ManagementResourceRegistrations for the root host resource final ModelNode hostAdd = new ModelNode(); hostAdd.get(OP).set(HostModelRegistrationHandler.OPERATION_NAME); hostAdd.get(NAME).set(resolvedHost); hostAdd.get(OP_ADDR).setEmptyList(); operationList.add(hostAdd); // Add a step to store the HC name ModelNode nameValue = hostName == null ? new ModelNode() : new ModelNode(hostName); final ModelNode writeName = Util.getWriteAttributeOperation(address, NAME, nameValue); operationList.add(writeName); } private void parseDomainController(final XMLExtendedStreamReader reader, final ModelNode address, final List<ModelNode> list) throws XMLStreamException { requireNoAttributes(reader); boolean hasLocal = false; boolean hasRemote = false; while (reader.hasNext() && reader.nextTag() != END_ELEMENT) { requireNamespace(reader, namespace); final Element element = Element.forName(reader.getLocalName()); switch (element) { case LOCAL: { if (hasLocal) { throw ControllerLogger.ROOT_LOGGER.childAlreadyDeclared(element.getLocalName(), Element.DOMAIN_CONTROLLER.getLocalName(), reader.getLocation()); } else if (hasRemote) { throw ControllerLogger.ROOT_LOGGER.childAlreadyDeclared(Element.REMOTE.getLocalName(), Element.DOMAIN_CONTROLLER.getLocalName(), reader.getLocation()); } parseLocalDomainController(reader, address, list); hasLocal = true; break; } case REMOTE: { if (hasRemote) { throw ControllerLogger.ROOT_LOGGER.childAlreadyDeclared(element.getLocalName(), Element.DOMAIN_CONTROLLER.getLocalName(), reader.getLocation()); } else if (hasLocal) { throw ControllerLogger.ROOT_LOGGER.childAlreadyDeclared(Element.LOCAL.getLocalName(), Element.DOMAIN_CONTROLLER.getLocalName(), reader.getLocation()); } parseRemoteDomainController(reader, address, list); hasRemote = true; break; } default: throw unexpectedElement(reader); } } if (!hasLocal && !hasRemote) { throw ControllerLogger.ROOT_LOGGER.domainControllerMustBeDeclared(Element.REMOTE.getLocalName(), Element.LOCAL.getLocalName(), reader.getLocation()); } if (hasLocal) { ModelNode localDc = new ModelNode(); localDc.get(LOCAL).setEmptyObject() ; final ModelNode update = Util.getWriteAttributeOperation(address, DOMAIN_CONTROLLER, localDc); list.add(update); } } private void parseLocalDomainController(final XMLExtendedStreamReader reader, final ModelNode address, final List<ModelNode> list) throws XMLStreamException { requireNoAttributes(reader); boolean hasDiscoveryOptions = false; Set<String> staticDiscoveryOptionNames = new HashSet<String>(); Set<String> discoveryOptionNames = new HashSet<String>(); while (reader.hasNext() && reader.nextTag() != END_ELEMENT) { requireNamespace(reader, namespace); final Element element = Element.forName(reader.getLocalName()); switch (element) { case DISCOVERY_OPTIONS: { if (hasDiscoveryOptions) { throw ControllerLogger.ROOT_LOGGER.alreadyDefined(element.getLocalName(), reader.getLocation()); } parseDiscoveryOptions(reader, address, list, staticDiscoveryOptionNames, discoveryOptionNames); hasDiscoveryOptions = true; break; } default: throw unexpectedElement(reader); } } } private void parseRemoteDomainController(final XMLExtendedStreamReader reader, final ModelNode address, final List<ModelNode> list) throws XMLStreamException { boolean requireDiscoveryOptions = false; boolean hasDiscoveryOptions = false; requireDiscoveryOptions = parseRemoteDomainControllerAttributes(reader, address, list); Set<String> types = new HashSet<String>(); Set<String> staticDiscoveryOptionNames = new HashSet<String>(); Set<String> discoveryOptionNames = new HashSet<String>(); while (reader.hasNext() && reader.nextTag() != END_ELEMENT) { requireNamespace(reader, namespace); final Element element = Element.forName(reader.getLocalName()); switch (element) { case IGNORED_RESOURCE: { parseIgnoredResource(reader, address, list, types); break; } case DISCOVERY_OPTIONS: { // Different from parseRemoteDomainController1_1 if (hasDiscoveryOptions) { throw ControllerLogger.ROOT_LOGGER.alreadyDefined(element.getLocalName(), reader.getLocation()); } parseDiscoveryOptions(reader, address, list, staticDiscoveryOptionNames, discoveryOptionNames); hasDiscoveryOptions = true; break; } default: throw unexpectedElement(reader); } } if (requireDiscoveryOptions && !hasDiscoveryOptions) { throw ControllerLogger.ROOT_LOGGER.discoveryOptionsMustBeDeclared(CommandLineConstants.ADMIN_ONLY, Attribute.ADMIN_ONLY_POLICY.getLocalName(), AdminOnlyDomainConfigPolicy.FETCH_FROM_MASTER.toString(), Element.DISCOVERY_OPTIONS.getLocalName(), Attribute.HOST.getLocalName(), Attribute.PORT.getLocalName(), reader.getLocation()); } } private boolean parseRemoteDomainControllerAttributes(final XMLExtendedStreamReader reader, final ModelNode address, final List<ModelNode> list) throws XMLStreamException { final ModelNode remoteDc = new ModelNode(); final ModelNode updateDc = remoteDc.get(REMOTE).setEmptyObject() ; // Handle attributes AdminOnlyDomainConfigPolicy adminOnlyPolicy = AdminOnlyDomainConfigPolicy.DEFAULT; boolean requireDiscoveryOptions = false; final int count = reader.getAttributeCount(); for (int i = 0; i < count; i++) { final String value = reader.getAttributeValue(i); if (!isNoNamespaceAttribute(reader, i)) { throw unexpectedAttribute(reader, i); } else { final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); switch (attribute) { case HOST: { DomainControllerWriteAttributeHandler.HOST.parseAndSetParameter(value, updateDc, reader); break; } case PORT: { DomainControllerWriteAttributeHandler.PORT.parseAndSetParameter(value, updateDc, reader); break; } case PROTOCOL: { DomainControllerWriteAttributeHandler.PROTOCOL.parseAndSetParameter(value, updateDc, reader); break; } case SECURITY_REALM: { DomainControllerWriteAttributeHandler.SECURITY_REALM.parseAndSetParameter(value, updateDc, reader); break; } case USERNAME: { DomainControllerWriteAttributeHandler.USERNAME.parseAndSetParameter(value, updateDc, reader); break; } case IGNORE_UNUSED_CONFIG: { DomainControllerWriteAttributeHandler.IGNORE_UNUSED_CONFIG.parseAndSetParameter(value, updateDc, reader); break; } case ADMIN_ONLY_POLICY: { DomainControllerWriteAttributeHandler.ADMIN_ONLY_POLICY.parseAndSetParameter(value, updateDc, reader); ModelNode nodeValue = updateDc.get(DomainControllerWriteAttributeHandler.ADMIN_ONLY_POLICY.getName()); if (nodeValue.getType() != ModelType.EXPRESSION) { adminOnlyPolicy = AdminOnlyDomainConfigPolicy.getPolicy(nodeValue.asString()); } break; } default: throw unexpectedAttribute(reader, i); } } } if (!updateDc.hasDefined(DomainControllerWriteAttributeHandler.HOST.getName())) { requireDiscoveryOptions = isRequireDiscoveryOptions(adminOnlyPolicy); } if (!updateDc.hasDefined(DomainControllerWriteAttributeHandler.PORT.getName())) { requireDiscoveryOptions = requireDiscoveryOptions || isRequireDiscoveryOptions(adminOnlyPolicy); } final ModelNode update = Util.getWriteAttributeOperation(address, DOMAIN_CONTROLLER, remoteDc); list.add(update); return requireDiscoveryOptions; } private boolean isRequireDiscoveryOptions(AdminOnlyDomainConfigPolicy adminOnlyPolicy) { return !isCachedDc && (runningMode != RunningMode.ADMIN_ONLY || adminOnlyPolicy == AdminOnlyDomainConfigPolicy.FETCH_FROM_MASTER); } private void parseIgnoredResource(final XMLExtendedStreamReader reader, final ModelNode address, final List<ModelNode> list, final Set<String> foundTypes) throws XMLStreamException { ModelNode op = new ModelNode(); op.get(OP).set(ADD); String type = null; final int count = reader.getAttributeCount(); for (int i = 0; i < count; i++) { if (!isNoNamespaceAttribute(reader, i)) { throw unexpectedAttribute(reader, i); } final String value = reader.getAttributeValue(i); final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); switch (attribute) { case TYPE: { if (!foundTypes.add(value)) { throw HostControllerLogger.ROOT_LOGGER.duplicateIgnoredResourceType(Element.IGNORED_RESOURCE.getLocalName(), value, reader.getLocation()); } type = value; break; } case WILDCARD: { IgnoredDomainTypeResourceDefinition.WILDCARD.parseAndSetParameter(value, op, reader); break; } default: throw unexpectedAttribute(reader, i); } } if (type == null) { throw ParseUtils.missingRequired(reader, Collections.singleton(Attribute.TYPE.getLocalName())); } ModelNode addr = op.get(OP_ADDR).set(address); addr.add(CORE_SERVICE, IGNORED_RESOURCES); addr.add(IGNORED_RESOURCE_TYPE, type); while (reader.hasNext() && reader.nextTag() != END_ELEMENT) { requireNamespace(reader, namespace); final Element element = Element.forName(reader.getLocalName()); switch (element) { case INSTANCE: { String name = ParseUtils.readStringAttributeElement(reader, NAME); IgnoredDomainTypeResourceDefinition.NAMES.parseAndAddParameterElement(name, op, reader); break; } default: throw unexpectedElement(reader); } } list.add(op); } protected void parseDiscoveryOptions(final XMLExtendedStreamReader reader, final ModelNode address, final List<ModelNode> list, final Set<String> staticDiscoveryOptionNames, final Set<String> discoveryOptionNames) throws XMLStreamException { requireNoAttributes(reader); // Handle elements while (reader.hasNext() && reader.nextTag() != END_ELEMENT) { requireNamespace(reader, namespace); final Element element = Element.forName(reader.getLocalName()); switch (element) { case DISCOVERY_OPTION: parseDiscoveryOption(reader, address, list, discoveryOptionNames); break; case STATIC_DISCOVERY: parseStaticDiscoveryOption(reader, address, list, staticDiscoveryOptionNames); break; default: throw unexpectedElement(reader); } } } protected void parseStaticDiscoveryOption(final XMLExtendedStreamReader reader, final ModelNode address, final List<ModelNode> list, final Set<String> staticDiscoveryOptionNames) throws XMLStreamException { // OP_ADDR will be set after parsing the NAME attribute final ModelNode staticDiscoveryOptionAddress = address.clone(); staticDiscoveryOptionAddress.add(CORE_SERVICE, DISCOVERY_OPTIONS); final ModelNode addOp = Util.getEmptyOperation(ADD, new ModelNode()); list.add(addOp); // Handle attributes final Set<Attribute> required = EnumSet.of(Attribute.NAME, Attribute.HOST, Attribute.PORT); final int count = reader.getAttributeCount(); for (int i = 0; i < count; i++) { requireNoNamespaceAttribute(reader, i); final String value = reader.getAttributeValue(i); final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); required.remove(attribute); switch (attribute) { case NAME: { if (!staticDiscoveryOptionNames.add(value)) { throw ParseUtils.duplicateNamedElement(reader, value); } addOp.get(OP_ADDR).set(staticDiscoveryOptionAddress).add(STATIC_DISCOVERY, value); break; } case HOST: { StaticDiscoveryResourceDefinition.HOST.parseAndSetParameter(value, addOp, reader); break; } case PROTOCOL: { StaticDiscoveryResourceDefinition.PROTOCOL.parseAndSetParameter(value, addOp, reader); break; } case PORT: { StaticDiscoveryResourceDefinition.PORT.parseAndSetParameter(value, addOp, reader); break; } default: throw unexpectedAttribute(reader, i); } } if (required.size() > 0) { throw missingRequired(reader, required); } requireNoContent(reader); } protected void parseDiscoveryOption(final XMLExtendedStreamReader reader, final ModelNode address, final List<ModelNode> list, final Set<String> discoveryOptionNames) throws XMLStreamException { // Handle attributes final ModelNode addOp = parseDiscoveryOptionAttributes(reader, address, list, discoveryOptionNames); // Handle elements while (reader.hasNext() && reader.nextTag() != END_ELEMENT) { requireNamespace(reader, namespace); final Element element = Element.forName(reader.getLocalName()); switch (element) { case PROPERTY: { parseDiscoveryOptionProperty(reader, addOp.get(PROPERTIES)); break; } default: throw unexpectedElement(reader); } } } private ModelNode parseDiscoveryOptionAttributes(final XMLExtendedStreamReader reader, final ModelNode address, final List<ModelNode> list, final Set<String> discoveryOptionNames) throws XMLStreamException { // OP_ADDR will be set after parsing the NAME attribute final ModelNode discoveryOptionAddress = address.clone(); discoveryOptionAddress.add(CORE_SERVICE, DISCOVERY_OPTIONS); final ModelNode addOp = Util.getEmptyOperation(ADD, new ModelNode()); list.add(addOp); final Set<Attribute> required = EnumSet.of(Attribute.NAME, Attribute.CODE); final int count = reader.getAttributeCount(); for (int i = 0; i < count; i++) { requireNoNamespaceAttribute(reader, i); final String value = reader.getAttributeValue(i); final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); required.remove(attribute); switch (attribute) { case NAME: { if (!discoveryOptionNames.add(value)) { throw ParseUtils.duplicateNamedElement(reader, value); } addOp.get(OP_ADDR).set(discoveryOptionAddress).add(DISCOVERY_OPTION, value); break; } case CODE: { DiscoveryOptionResourceDefinition.CODE.parseAndSetParameter(value, addOp, reader); break; } case MODULE: { DiscoveryOptionResourceDefinition.MODULE.parseAndSetParameter(value, addOp, reader); break; } default: throw unexpectedAttribute(reader, i); } } if (required.size() > 0) { throw missingRequired(reader, required); } return addOp; } protected void parseDiscoveryOptionProperty(XMLExtendedStreamReader reader, ModelNode discoveryOptionProperties) throws XMLStreamException { String propertyName = null; String propertyValue = null; EnumSet<Attribute> required = EnumSet.of(Attribute.NAME, Attribute.VALUE); final int count = reader.getAttributeCount(); for (int i = 0; i < count; i++) { requireNoNamespaceAttribute(reader, i); final String value = reader.getAttributeValue(i); final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); required.remove(attribute); switch (attribute) { case NAME: { propertyName = value; break; } case VALUE: { propertyValue = value; break; } default: throw unexpectedAttribute(reader, i); } } if (required.size() > 0) { throw missingRequired(reader, required); } discoveryOptionProperties.add(propertyName, propertyValue); requireNoContent(reader); } private void parseJvms(final XMLExtendedStreamReader reader, final ModelNode address, final List<ModelNode> list) throws XMLStreamException { requireNoAttributes(reader); final Set<String> names = new HashSet<String>(); // Handle elements while (reader.hasNext() && reader.nextTag() != END_ELEMENT) { requireNamespace(reader, namespace); final Element element = Element.forName(reader.getLocalName()); switch (element) { case JVM: JvmXml.parseJvm(reader, address, namespace, list, names, false); break; default: throw unexpectedElement(reader); } } } private void parseServersAttributes(final XMLExtendedStreamReader reader, final ModelNode parentAddress, final List<ModelNode> list) throws XMLStreamException { // Handle attributes final int count = reader.getAttributeCount(); for (int i = 0; i < count; i++) { final String value = reader.getAttributeValue(i); if (!isNoNamespaceAttribute(reader, i)) { throw unexpectedAttribute(reader, i); } else { final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); switch (attribute) { case DIRECTORY_GROUPING: { final ModelNode address = parentAddress.clone(); list.add(Util.getWriteAttributeOperation(address, DIRECTORY_GROUPING, HostResourceDefinition.DIRECTORY_GROUPING.parse(value,reader))); break; } default: throw unexpectedAttribute(reader, i); } } } } private void parseServers(final XMLExtendedStreamReader reader, final ModelNode address, final List<ModelNode> list) throws XMLStreamException { parseServersAttributes(reader, address, list); // Handle elements final Set<String> names = new HashSet<String>(); while (reader.hasNext() && reader.nextTag() != END_ELEMENT) { requireNamespace(reader, namespace); final Element element = Element.forName(reader.getLocalName()); switch (element) { case SERVER: parseServer(reader, address, list, names); break; default: throw unexpectedElement(reader); } } } private void parseServer(final XMLExtendedStreamReader reader, final ModelNode parentAddress, final List<ModelNode> list, final Set<String> serverNames) throws XMLStreamException { // Handle attributes final ModelNode addUpdate = parseServerAttributes(reader, parentAddress, serverNames); final ModelNode address = addUpdate.require(OP_ADDR); list.add(addUpdate); // Handle elements parseServerContent(reader, addUpdate, address, list); } private void parseServerContent(final XMLExtendedStreamReader reader, final ModelNode serverAddOperation, final ModelNode serverAddress, final List<ModelNode> list) throws XMLStreamException { boolean sawJvm = false; boolean sawSystemProperties = false; boolean sawSocketBinding = false; boolean sawSSL = false; final Set<String> interfaceNames = new HashSet<String>(); while (reader.hasNext() && reader.nextTag() != END_ELEMENT) { requireNamespace(reader, namespace); final Element element = Element.forName(reader.getLocalName()); switch (element) { case INTERFACES: { // THIS IS DIFFERENT FROM 1.0 parseInterfaces(reader, interfaceNames, serverAddress, namespace, list, true); break; } case JVM: { if (sawJvm) { throw ControllerLogger.ROOT_LOGGER.alreadyDefined(element.getLocalName(), reader.getLocation()); } JvmXml.parseJvm(reader, serverAddress, namespace, list, new HashSet<String>(), true); sawJvm = true; break; } case PATHS: { parsePaths(reader, serverAddress, namespace, list, true); break; } case SOCKET_BINDINGS: { if (sawSocketBinding) { throw ControllerLogger.ROOT_LOGGER.alreadyDefined(element.getLocalName(), reader.getLocation()); } parseServerSocketBindings(reader, serverAddOperation); sawSocketBinding = true; break; } case SSL: { if (sawSSL) { throw ControllerLogger.ROOT_LOGGER.alreadyDefined(element.getLocalName(), reader.getLocation()); } parseServerSsl(serverAddress, reader, list); sawSSL = true; break; } case SYSTEM_PROPERTIES: { if (sawSystemProperties) { throw ControllerLogger.ROOT_LOGGER.alreadyDefined(element.getLocalName(), reader.getLocation()); } parseSystemProperties(reader, serverAddress, namespace, list, false); sawSystemProperties = true; break; } default: throw unexpectedElement(reader); } } } private ModelNode parseServerAttributes(final XMLExtendedStreamReader reader, final ModelNode parentAddress, final Set<String> serverNames) throws XMLStreamException { final ModelNode addUpdate = new ModelNode(); addUpdate.get(OP).set(ADD); final Set<Attribute> required = EnumSet.of(Attribute.NAME, Attribute.GROUP); final int count = reader.getAttributeCount(); for (int i = 0; i < count; i++) { final String value = reader.getAttributeValue(i); if (!isNoNamespaceAttribute(reader, i)) { throw unexpectedAttribute(reader, i); } else { final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); required.remove(attribute); switch (attribute) { case NAME: { if (!serverNames.add(value)) { throw ControllerLogger.ROOT_LOGGER.duplicateDeclaration("server", value, reader.getLocation()); } final ModelNode address = parentAddress.clone().add(SERVER_CONFIG, value); addUpdate.get(OP_ADDR).set(address); break; } case GROUP: { ServerConfigResourceDefinition.GROUP.parseAndSetParameter(value, addUpdate, reader); break; } case AUTO_START: { ServerConfigResourceDefinition.AUTO_START.parseAndSetParameter(value, addUpdate, reader); break; } case UPDATE_AUTO_START_WITH_SERVER_STATUS: { ServerConfigResourceDefinition.UPDATE_AUTO_START_WITH_SERVER_STATUS.parseAndSetParameter(value, addUpdate, reader); break; } default: throw unexpectedAttribute(reader, i); } } } if (required.size() > 0) { throw missingRequired(reader, required); } return addUpdate; } private void parseServerSocketBindings(final XMLExtendedStreamReader reader, final ModelNode serverAddOperation) throws XMLStreamException { // Handle attributes final int count = reader.getAttributeCount(); for (int i = 0; i < count; i++) { final String value = reader.getAttributeValue(i); if (!isNoNamespaceAttribute(reader, i)) { throw ParseUtils.unexpectedAttribute(reader, i); } else { final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); switch (attribute) { case SOCKET_BINDING_GROUP: { ServerConfigResourceDefinition.SOCKET_BINDING_GROUP.parseAndSetParameter(value, serverAddOperation, reader); break; } case DEFAULT_INTERFACE: { ServerConfigResourceDefinition.SOCKET_BINDING_DEFAULT_INTERFACE.parseAndSetParameter(value, serverAddOperation, reader); break; } case PORT_OFFSET: { ServerConfigResourceDefinition.SOCKET_BINDING_PORT_OFFSET.parseAndSetParameter(value, serverAddOperation, reader); break; } default: throw unexpectedAttribute(reader, i); } } } // Handle elements requireNoContent(reader); } private void parseServerSsl(final ModelNode parentAddress, final XMLExtendedStreamReader reader, final List<ModelNode> operations) throws XMLStreamException { ModelNode addOp = new ModelNode(); addOp.get(OP).set(ADD); final ModelNode address = parentAddress.clone(); address.add(SSL, LOOPBACK); addOp.get(OP_ADDR).set(address); operations.add(addOp); final int count = reader.getAttributeCount(); for (int i = 0; i < count; i++) { final String value = reader.getAttributeValue(i); if (!isNoNamespaceAttribute(reader, i)) { throw ParseUtils.unexpectedAttribute(reader, i); } else { final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); switch (attribute) { case SSL_PROTOCOL: { SslLoopbackResourceDefinition.SSL_PROTOCOCOL.parseAndSetParameter(value, addOp, reader); break; } case TRUST_MANAGER_ALGORITHM: { SslLoopbackResourceDefinition.TRUST_MANAGER_ALGORITHM.parseAndSetParameter(value, addOp, reader); break; } case TRUSTSTORE_TYPE: { SslLoopbackResourceDefinition.TRUSTSTORE_TYPE.parseAndSetParameter(value, addOp, reader); break; } case TRUSTSTORE_PATH: { SslLoopbackResourceDefinition.TRUSTSTORE_PATH.parseAndSetParameter(value, addOp, reader); break; } case TRUSTSTORE_PASSWORD: { SslLoopbackResourceDefinition.TRUSTSTORE_PASSWORD.parseAndSetParameter(value, addOp, reader); break; } default: throw unexpectedAttribute(reader, i); } } } requireNoContent(reader); } private void parseHostProfile(XMLExtendedStreamReader reader, ModelNode address, List<ModelNode> list) throws XMLStreamException { // Attributes requireNoAttributes(reader); // Content final Map<String, List<ModelNode>> profileOps = new LinkedHashMap<String, List<ModelNode>>(); while (reader.hasNext() && reader.nextTag() != END_ELEMENT) { if (Element.forName(reader.getLocalName()) != Element.SUBSYSTEM) { throw unexpectedElement(reader); } String namespace = reader.getNamespaceURI(); if (profileOps.containsKey(namespace)) { throw ControllerLogger.ROOT_LOGGER.duplicateDeclaration("subsystem", reader.getLocation()); } // parse subsystem final List<ModelNode> subsystems = new ArrayList<ModelNode>(); reader.handleAny(subsystems); profileOps.put(namespace, subsystems); } // Let extensions modify the profile Set<ProfileParsingCompletionHandler> completionHandlers = extensionRegistry.getProfileParsingCompletionHandlers(); for (ProfileParsingCompletionHandler completionHandler : completionHandlers) { completionHandler.handleProfileParsingCompletion(profileOps, list); } for (List<ModelNode> subsystems : profileOps.values()) { for (final ModelNode update : subsystems) { // Process relative subsystem path address final ModelNode subsystemAddress = address.clone(); for (final Property path : update.get(OP_ADDR).asPropertyList()) { subsystemAddress.add(path.getName(), path.getValue().asString()); } update.get(OP_ADDR).set(subsystemAddress); list.add(update); } } } private void parseSocketBindingGroup(final XMLExtendedStreamReader reader, final Set<String> interfaces, final ModelNode address, final List<ModelNode> updates) throws XMLStreamException { // unique names for both socket-binding and outbound-socket-binding(s) final Set<String> uniqueBindingNames = new HashSet<String>(); ModelNode op = Util.getEmptyOperation(ADD, null); // Handle attributes String socketBindingGroupName = null; final EnumSet<Attribute> required = EnumSet.of(Attribute.NAME, Attribute.DEFAULT_INTERFACE); final int count = reader.getAttributeCount(); for (int i = 0; i < count; i++) { final String value = reader.getAttributeValue(i); if (!isNoNamespaceAttribute(reader, i)) { throw unexpectedAttribute(reader, i); } final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i)); switch (attribute) { case NAME: { socketBindingGroupName = value; required.remove(attribute); break; } case DEFAULT_INTERFACE: { SocketBindingGroupResourceDefinition.DEFAULT_INTERFACE.parseAndSetParameter(value, op, reader); required.remove(attribute); if (op.get(AbstractSocketBindingGroupResourceDefinition.DEFAULT_INTERFACE.getName()).getType() != ModelType.EXPRESSION && !interfaces.contains(value)) { throw ControllerLogger.ROOT_LOGGER.unknownInterface(value, Attribute.DEFAULT_INTERFACE.getLocalName(), Element.INTERFACES.getLocalName(), reader.getLocation()); } break; } case PORT_OFFSET: { SocketBindingGroupResourceDefinition.PORT_OFFSET.parseAndSetParameter(value, op, reader); break; } default: throw ParseUtils.unexpectedAttribute(reader, i); } } if (!required.isEmpty()) { throw missingRequired(reader, required); } ModelNode groupAddress = address.clone().add(SOCKET_BINDING_GROUP, socketBindingGroupName); op.get(OP_ADDR).set(groupAddress); updates.add(op); // Handle elements while (reader.nextTag() != END_ELEMENT) { requireNamespace(reader, namespace); final Element element = Element.forName(reader.getLocalName()); switch (element) { case SOCKET_BINDING: { final String bindingName = parseSocketBinding(reader, interfaces, groupAddress, updates); if (!uniqueBindingNames.add(bindingName)) { throw ControllerLogger.ROOT_LOGGER.alreadyDeclared(Element.SOCKET_BINDING.getLocalName(), Element.OUTBOUND_SOCKET_BINDING.getLocalName(), bindingName, Element.SOCKET_BINDING_GROUP.getLocalName(), socketBindingGroupName, reader.getLocation()); } break; } case OUTBOUND_SOCKET_BINDING: { final String bindingName = parseOutboundSocketBinding(reader, interfaces, groupAddress, updates); if (!uniqueBindingNames.add(bindingName)) { throw ControllerLogger.ROOT_LOGGER.alreadyDeclared(Element.SOCKET_BINDING.getLocalName(), Element.OUTBOUND_SOCKET_BINDING.getLocalName(), bindingName, Element.SOCKET_BINDING_GROUP.getLocalName(), socketBindingGroupName, reader.getLocation()); } break; } default: throw unexpectedElement(reader); } } } /* * ManagamentXmlDelegate Methods */ @Override public boolean parseManagementInterfaces(XMLExtendedStreamReader reader, ModelNode address, List<ModelNode> operationsList) throws XMLStreamException { requireNoAttributes(reader); boolean interfaceDefined = false; while (reader.hasNext() && reader.nextTag() != END_ELEMENT) { requireNamespace(reader, namespace); final Element element = Element.forName(reader.getLocalName()); switch (element) { case NATIVE_INTERFACE: { interfaceDefined = true; parseManagementInterface(reader, address, false, operationsList); break; } case HTTP_INTERFACE: { interfaceDefined = true; parseManagementInterface(reader, address, true, operationsList); break; } default: { throw unexpectedElement(reader); } } } if (!interfaceDefined) { throw missingOneOf(reader, EnumSet.of(Element.NATIVE_INTERFACE, Element.HTTP_INTERFACE)); } return true; } @Override public boolean parseAuditLog(XMLExtendedStreamReader reader, ModelNode address, List<ModelNode> list) throws XMLStreamException { auditLogDelegate.parseAuditLog(reader, address, namespace, list); return true; } }