/*
* 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.security;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CODE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM;
import static org.jboss.as.controller.parsing.ParseUtils.invalidAttributeValue;
import static org.jboss.as.controller.parsing.ParseUtils.missingRequired;
import static org.jboss.as.controller.parsing.ParseUtils.requireAttributes;
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 static org.jboss.as.security.Constants.ACL;
import static org.jboss.as.security.Constants.ACL_MODULE;
import static org.jboss.as.security.Constants.AUDIT;
import static org.jboss.as.security.Constants.AUTHENTICATION;
import static org.jboss.as.security.Constants.AUTHORIZATION;
import static org.jboss.as.security.Constants.AUTH_MODULE;
import static org.jboss.as.security.Constants.CLASSIC;
import static org.jboss.as.security.Constants.IDENTITY_TRUST;
import static org.jboss.as.security.Constants.JASPI;
import static org.jboss.as.security.Constants.JSSE;
import static org.jboss.as.security.Constants.KEYSTORE;
import static org.jboss.as.security.Constants.KEY_MANAGER;
import static org.jboss.as.security.Constants.LOGIN_MODULE;
import static org.jboss.as.security.Constants.LOGIN_MODULE_STACK;
import static org.jboss.as.security.Constants.MAPPING;
import static org.jboss.as.security.Constants.MAPPING_MODULE;
import static org.jboss.as.security.Constants.POLICY_MODULE;
import static org.jboss.as.security.Constants.PROVIDER_MODULE;
import static org.jboss.as.security.Constants.SECURITY_DOMAIN;
import static org.jboss.as.security.Constants.TRUSTSTORE;
import static org.jboss.as.security.Constants.TRUST_MANAGER;
import static org.jboss.as.security.Constants.TRUST_MODULE;
import static org.jboss.as.security.Constants.VAULT;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.PathElement;
import org.jboss.as.controller.PropertiesAttributeDefinition;
import org.jboss.as.controller.operations.common.Util;
import org.jboss.as.security.logging.SecurityLogger;
import org.jboss.dmr.ModelNode;
import org.jboss.staxmapper.XMLElementReader;
import org.jboss.staxmapper.XMLExtendedStreamReader;
/**
* The root element parser for the Security subsystem.
*
* @author Marcus Moyses
* @author Darran Lofthouse
* @author Brian Stansberry
* @author Jason T. Greene
* @author Anil Saldhana
* @author Tomaz Cerar
*/
public class SecuritySubsystemParser implements XMLStreamConstants, XMLElementReader<List<ModelNode>>, ModulesMap {
private Map<String, Integer> moduleNames;
protected SecuritySubsystemParser() {
}
@Override
public void readElement(XMLExtendedStreamReader reader, List<ModelNode> operations) throws XMLStreamException {
PathAddress address = PathAddress.pathAddress(PathElement.pathElement(SUBSYSTEM, SecurityExtension.SUBSYSTEM_NAME));
final ModelNode subsystemNode = Util.createAddOperation(address);
operations.add(subsystemNode);
requireNoAttributes(reader);
final EnumSet<Element> visited = EnumSet.noneOf(Element.class);
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
final Element element = Element.forName(reader.getLocalName());
if (!visited.add(element)) {
throw unexpectedElement(reader);
}
readElement(reader, element, operations, address, subsystemNode);
}
}
protected void readElement(final XMLExtendedStreamReader reader, final Element element, final List<ModelNode> operations,
final PathAddress subsystemPath, final ModelNode subsystemNode) throws XMLStreamException {
switch (element) {
case SECURITY_MANAGEMENT: {
parseSecurityManagement(reader, subsystemNode);
break;
}
case SECURITY_DOMAINS: {
final List<ModelNode> securityDomainsUpdates = parseSecurityDomains(reader, subsystemPath);
if (securityDomainsUpdates != null) {
operations.addAll(securityDomainsUpdates);
}
break;
}
case SECURITY_PROPERTIES:
reader.discardRemainder();
break;
case VAULT: {
final Namespace schemaVer = Namespace.forUri(reader.getNamespaceURI());
if (schemaVer == Namespace.SECURITY_1_0) {
throw unexpectedElement(reader);
}
final int count = reader.getAttributeCount();
ModelNode vault = createAddOperation(subsystemPath, VAULT, CLASSIC);
if (count > 1) {
throw unexpectedAttribute(reader, count);
}
for (int i = 0; i < count; i++) {
requireNoNamespaceAttribute(reader, i);
final String value = reader.getAttributeValue(i);
final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i));
switch (attribute) {
case CODE: {
vault.get(CODE).set(value);
break;
}
default:
throw unexpectedAttribute(reader, i);
}
}
parseProperties(Element.VAULT_OPTION.getLocalName(), reader, vault, VaultResourceDefinition.OPTIONS);
operations.add(vault);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
private void parseSecurityManagement(final XMLExtendedStreamReader reader, final ModelNode operation)
throws XMLStreamException {
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));
switch (attribute) {
case DEEP_COPY_SUBJECT_MODE: {
SecuritySubsystemRootResourceDefinition.DEEP_COPY_SUBJECT_MODE.parseAndSetParameter(value, operation, reader);
break;
}
case INITIALIZE_JACC: {
SecuritySubsystemRootResourceDefinition.INITIALIZE_JACC.parseAndSetParameter(value, operation, reader);
break;
}
default:
throw unexpectedAttribute(reader, i);
}
}
requireNoContent(reader);
}
private List<ModelNode> parseSecurityDomains(final XMLExtendedStreamReader reader, final PathAddress parentAddress)
throws XMLStreamException {
requireNoAttributes(reader);
List<ModelNode> list = new ArrayList<ModelNode>();
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
final Element element = Element.forName(reader.getLocalName());
switch (element) {
case SECURITY_DOMAIN: {
parseSecurityDomain(list, reader, parentAddress);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
return list;
}
private void parseSecurityDomain(List<ModelNode> list, XMLExtendedStreamReader reader, PathAddress parentAddress) throws XMLStreamException {
ModelNode op = Util.createAddOperation();
list.add(op);
PathElement secDomainPath = null;
EnumSet<Attribute> required = EnumSet.of(Attribute.NAME);
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 (value == null || value.length() == 0) {
throw invalidAttributeValue(reader, i);
}
secDomainPath = PathElement.pathElement(SECURITY_DOMAIN, value);
break;
}
case CACHE_TYPE: {
SecurityDomainResourceDefinition.CACHE_TYPE.parseAndSetParameter(value, op, reader);
break;
}
default:
throw unexpectedAttribute(reader, i);
}
}
if (required.size() > 0) {
throw missingRequired(reader, required);
}
final PathAddress address = parentAddress.append(secDomainPath);
op.get(OP_ADDR).set(address.toModelNode());
final EnumSet<Element> visited = EnumSet.noneOf(Element.class);
moduleNames = new HashMap<String, Integer>();
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
final Element element = Element.forName(reader.getLocalName());
if (!visited.add(element)) {
throw unexpectedElement(reader);
}
switch (element) {
case AUTHENTICATION: {
if (visited.contains(Element.AUTHENTICATION_JASPI)) {
throw SecurityLogger.ROOT_LOGGER.xmlStreamExceptionAuth(reader.getLocation());
}
parseAuthentication(list, address, reader);
break;
}
case AUTHORIZATION: {
parseAuthorization(list, address, reader);
break;
}
case ACL: {
parseACL(list, address, reader);
break;
}
case AUDIT: {
parseAudit(list, address, reader);
break;
}
case IDENTITY_TRUST: {
parseIdentityTrust(list, address, reader);
break;
}
case MAPPING: {
parseMapping(list, address, reader);
break;
}
case AUTHENTICATION_JASPI: {
if (visited.contains(Element.AUTHENTICATION)) { throw SecurityLogger.ROOT_LOGGER.xmlStreamExceptionAuth(reader.getLocation()); }
parseAuthenticationJaspi(list, address, reader);
break;
}
case JSSE: {
parseJSSE(list, address, reader);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
moduleNames.clear();
}
private void parseAuthentication(List<ModelNode> list, PathAddress parentAddress, XMLExtendedStreamReader reader)
throws XMLStreamException {
requireNoAttributes(reader);
PathAddress address = parentAddress.append(AUTHENTICATION, CLASSIC);
ModelNode op = Util.createAddOperation(address);
list.add(op);
parseLoginModules(reader, address, list);
}
private void parseLoginModules(XMLExtendedStreamReader reader, PathAddress parentAddress, List<ModelNode> list) throws XMLStreamException {
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
final Element element = Element.forName(reader.getLocalName());
switch (element) {
case LOGIN_MODULE: {
EnumSet<Attribute> required = EnumSet.of(Attribute.CODE, Attribute.FLAG);
EnumSet<Attribute> notAllowed = EnumSet.of(Attribute.TYPE, Attribute.LOGIN_MODULE_STACK_REF);
parseCommonModule(reader, parentAddress, LOGIN_MODULE, required, notAllowed, list);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
}
private ModelNode appendAddOperation(List<ModelNode> list, PathAddress parentAddress, String name, String value) {
ModelNode op = createAddOperation(parentAddress, name, value);
list.add(op);
return op;
}
private ModelNode createAddOperation(PathAddress parentAddress, String name, String value) {
return Util.createAddOperation(parentAddress.append(name, value));
}
private void parseAuthorization(List<ModelNode> list, PathAddress parentAddress, XMLExtendedStreamReader reader) throws XMLStreamException {
requireNoAttributes(reader);
PathAddress address = parentAddress.append(AUTHORIZATION, CLASSIC);
ModelNode op = Util.createAddOperation(address);
list.add(op);
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
final Element element = Element.forName(reader.getLocalName());
switch (element) {
case POLICY_MODULE: {
EnumSet<Attribute> required = EnumSet.of(Attribute.CODE, Attribute.FLAG);
EnumSet<Attribute> notAllowed = EnumSet.of(Attribute.TYPE, Attribute.LOGIN_MODULE_STACK_REF);
parseCommonModule(reader, address, POLICY_MODULE, required, notAllowed, list);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
}
private void parseACL(List<ModelNode> list, PathAddress parentAddress, XMLExtendedStreamReader reader) throws XMLStreamException {
requireNoAttributes(reader);
PathAddress address = parentAddress.append(ACL, CLASSIC);
ModelNode op = Util.createAddOperation(address);
list.add(op);
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
final Element element = Element.forName(reader.getLocalName());
switch (element) {
case ACL_MODULE: {
EnumSet<Attribute> required = EnumSet.of(Attribute.CODE, Attribute.FLAG);
EnumSet<Attribute> notAllowed = EnumSet.of(Attribute.TYPE, Attribute.LOGIN_MODULE_STACK_REF);
parseCommonModule(reader, address, ACL_MODULE, required, notAllowed, list);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
}
private void parseAudit(List<ModelNode> list, PathAddress parentAddress, XMLExtendedStreamReader reader) throws XMLStreamException {
requireNoAttributes(reader);
PathAddress address = parentAddress.append(AUDIT, CLASSIC);
ModelNode op = Util.createAddOperation(address);
list.add(op);
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
final Element element = Element.forName(reader.getLocalName());
switch (element) {
case PROVIDER_MODULE: {
EnumSet<Attribute> required = EnumSet.of(Attribute.CODE);
EnumSet<Attribute> notAllowed = EnumSet.of(Attribute.TYPE, Attribute.FLAG, Attribute.LOGIN_MODULE_STACK_REF);
parseCommonModule(reader, address, PROVIDER_MODULE, required, notAllowed, list);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
}
private void parseIdentityTrust(List<ModelNode> list, PathAddress parentAddress, XMLExtendedStreamReader reader) throws XMLStreamException {
requireNoAttributes(reader);
PathAddress address = parentAddress.append(IDENTITY_TRUST, CLASSIC);
ModelNode op = Util.createAddOperation(address);
list.add(op);
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
final Element element = Element.forName(reader.getLocalName());
switch (element) {
case TRUST_MODULE: {
EnumSet<Attribute> required = EnumSet.of(Attribute.CODE, Attribute.FLAG);
EnumSet<Attribute> notAllowed = EnumSet.of(Attribute.TYPE, Attribute.LOGIN_MODULE_STACK_REF);
parseCommonModule(reader, address, TRUST_MODULE, required, notAllowed, list);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
}
private void parseMapping(List<ModelNode> list, PathAddress parentAddress, XMLExtendedStreamReader reader) throws XMLStreamException {
requireNoAttributes(reader);
PathAddress address = parentAddress.append(MAPPING, CLASSIC);
ModelNode op = Util.createAddOperation(address);
list.add(op);
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
final Element element = Element.forName(reader.getLocalName());
switch (element) {
case MAPPING_MODULE: {
EnumSet<Attribute> required = EnumSet.of(Attribute.CODE);
EnumSet<Attribute> notAllowed = EnumSet.of(Attribute.FLAG, Attribute.LOGIN_MODULE_STACK_REF);
parseCommonModule(reader, address, MAPPING_MODULE, required, notAllowed, list);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
}
private void parseCommonModule(XMLExtendedStreamReader reader, final PathAddress parentAddress, final String keyName, EnumSet<Attribute> required,
EnumSet<Attribute> notAllowed, List<ModelNode> list) throws XMLStreamException {
ModelNode node = Util.createAddOperation(parentAddress);
String code = null;
String name = null;
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));
if (notAllowed.contains(attribute)) { throw unexpectedAttribute(reader, i); }
required.remove(attribute);
switch (attribute) {
case CODE: {
code = value;
LoginModuleResourceDefinition.CODE.parseAndSetParameter(value, node, reader);
break;
}
case FLAG: {
LoginModuleResourceDefinition.FLAG.parseAndSetParameter(value, node, reader);
break;
}
case TYPE: {
MappingModuleDefinition.TYPE.parseAndSetParameter(value, node, reader);
break;
}
case MODULE: {
LoginModuleResourceDefinition.MODULE.parseAndSetParameter(value, node, reader);
break;
}
case LOGIN_MODULE_STACK_REF: {
JASPIMappingModuleDefinition.LOGIN_MODULE_STACK_REF.parseAndSetParameter(value, node, reader);
break;
}
case NAME: {
name = value;
break;
}
default:
throw unexpectedAttribute(reader, i);
}
}
if (name == null) {
name = code;
}
String key = keyName + "-" + name;
if (moduleNames.put(key, 1) != null) { //is case user configures duplicate login-module with same code, we generate name for him.
for (int i = 2; ; i++) {
name = code + "-" + i;
key = keyName + "-" + name;
if (!moduleNames.containsKey(key)) {
moduleNames.put(key, i);
break;
}
}
}
node.get(OP_ADDR).set(parentAddress.append(keyName, name).toModelNode());
if (required.size() > 0) {
throw missingRequired(reader, required);
}
parseProperties(Element.MODULE_OPTION.getLocalName(), reader, node, LoginModuleResourceDefinition.MODULE_OPTIONS);
list.add(node);
}
private void parseAuthenticationJaspi(List<ModelNode> list, PathAddress parentAddress, XMLExtendedStreamReader reader) throws XMLStreamException {
requireNoAttributes(reader);
PathAddress address = parentAddress.append(AUTHENTICATION, JASPI);
ModelNode op = Util.createAddOperation(address);
list.add(op);
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
final Element element = Element.forName(reader.getLocalName());
switch (element) {
case LOGIN_MODULE_STACK: {
parseLoginModuleStack(list, address, reader);
break;
}
case AUTH_MODULE: {
parseAuthModule(list, reader, address);
break;
}
default: {
throw unexpectedElement(reader);
}
}
}
}
private void parseAuthModule(List<ModelNode> list, XMLExtendedStreamReader reader, PathAddress parentAddress) throws XMLStreamException {
Namespace schemaVer = Namespace.forUri(reader.getNamespaceURI());
EnumSet<Attribute> required = EnumSet.of(Attribute.CODE);
final EnumSet<Attribute> notAllowed;
// in version 1.2 of the schema the optional flag attribute has been included.
switch (schemaVer) {
case SECURITY_1_0:
case SECURITY_1_1:
notAllowed = EnumSet.of(Attribute.TYPE, Attribute.FLAG);
break;
default:
notAllowed = EnumSet.of(Attribute.TYPE);
}
parseCommonModule(reader, parentAddress, AUTH_MODULE, required, notAllowed, list);
}
private void parseLoginModuleStack(List<ModelNode> list, PathAddress parentAddress, XMLExtendedStreamReader reader) throws XMLStreamException {
EnumSet<Attribute> required = EnumSet.of(Attribute.NAME);
String name = null;
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 (value == null) { throw invalidAttributeValue(reader, i); }
name = value;
break;
}
default:
throw unexpectedAttribute(reader, i);
}
}
if (required.size() > 0) {
throw missingRequired(reader, required);
}
PathAddress address = parentAddress.append(LOGIN_MODULE_STACK, name);
ModelNode op = Util.createAddOperation(address);
list.add(op);
parseLoginModules(reader, address, list);
}
private void parseProperties(String childElementName, XMLExtendedStreamReader reader, ModelNode node, PropertiesAttributeDefinition attribute) throws XMLStreamException {
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
final Element element = Element.forName(reader.getLocalName());
if (childElementName.equals(element.getLocalName())) {
final String[] array = requireAttributes(reader, org.jboss.as.controller.parsing.Attribute.NAME.getLocalName(), org.jboss.as.controller.parsing.Attribute.VALUE.getLocalName());
attribute.parseAndAddParameterElement(array[0], array[1], node, reader);
} else {
throw unexpectedElement(reader);
}
requireNoContent(reader);
}
}
private void parseJSSE(List<ModelNode> list, PathAddress parentAddress, XMLExtendedStreamReader reader) throws XMLStreamException {
ModelNode op = appendAddOperation(list, parentAddress, JSSE, CLASSIC);
EnumSet<Attribute> visited = EnumSet.noneOf(Attribute.class);
EnumSet<Attribute> required = EnumSet.noneOf(Attribute.class);
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));
switch (attribute) {
case KEYSTORE_PASSWORD: {
ComplexAttributes.PASSWORD.parseAndSetParameter(value, op.get(KEYSTORE), reader);
visited.add(attribute);
break;
}
case KEYSTORE_TYPE: {
ComplexAttributes.TYPE.parseAndSetParameter(value, op.get(KEYSTORE), reader);
required.add(Attribute.KEYSTORE_PASSWORD);
break;
}
case KEYSTORE_URL: {
ComplexAttributes.URL.parseAndSetParameter(value, op.get(KEYSTORE), reader);
required.add(Attribute.KEYSTORE_PASSWORD);
break;
}
case KEYSTORE_PROVIDER: {
ComplexAttributes.PROVIDER.parseAndSetParameter(value, op.get(KEYSTORE), reader);
required.add(Attribute.KEYSTORE_PASSWORD);
break;
}
case KEYSTORE_PROVIDER_ARGUMENT: {
ComplexAttributes.PROVIDER_ARGUMENT.parseAndSetParameter(value, op.get(KEYSTORE), reader);
required.add(Attribute.KEYSTORE_PASSWORD);
break;
}
case KEY_MANAGER_FACTORY_PROVIDER: {
ComplexAttributes.PROVIDER.parseAndSetParameter(value, op.get(KEY_MANAGER), reader);
break;
}
case KEY_MANAGER_FACTORY_ALGORITHM: {
ComplexAttributes.ALGORITHM.parseAndSetParameter(value, op.get(KEY_MANAGER), reader);
break;
}
case TRUSTSTORE_PASSWORD: {
ComplexAttributes.PASSWORD.parseAndSetParameter(value, op.get(TRUSTSTORE), reader);
visited.add(attribute);
break;
}
case TRUSTSTORE_TYPE: {
ComplexAttributes.TYPE.parseAndSetParameter(value, op.get(TRUSTSTORE), reader);
required.add(Attribute.TRUSTSTORE_PASSWORD);
break;
}
case TRUSTSTORE_URL: {
ComplexAttributes.URL.parseAndSetParameter(value, op.get(TRUSTSTORE), reader);
required.add(Attribute.TRUSTSTORE_PASSWORD);
break;
}
case TRUSTSTORE_PROVIDER: {
ComplexAttributes.PROVIDER.parseAndSetParameter(value, op.get(TRUSTSTORE), reader);
required.add(Attribute.TRUSTSTORE_PASSWORD);
break;
}
case TRUSTSTORE_PROVIDER_ARGUMENT: {
ComplexAttributes.PROVIDER_ARGUMENT.parseAndSetParameter(value, op.get(TRUSTSTORE), reader);
required.add(Attribute.TRUSTSTORE_PASSWORD);
break;
}
case TRUST_MANAGER_FACTORY_PROVIDER: {
ComplexAttributes.PROVIDER.parseAndSetParameter(value, op.get(TRUST_MANAGER), reader);
break;
}
case TRUST_MANAGER_FACTORY_ALGORITHM: {
ComplexAttributes.ALGORITHM.parseAndSetParameter(value, op.get(TRUST_MANAGER), reader);
break;
}
case CLIENT_ALIAS: {
JSSEResourceDefinition.CLIENT_ALIAS.parseAndSetParameter(value, op, reader);
break;
}
case SERVER_ALIAS: {
JSSEResourceDefinition.SERVER_ALIAS.parseAndSetParameter(value, op, reader);
break;
}
case CLIENT_AUTH: {
JSSEResourceDefinition.CLIENT_AUTH.parseAndSetParameter(value, op, reader);
break;
}
case SERVICE_AUTH_TOKEN: {
JSSEResourceDefinition.SERVICE_AUTH_TOKEN.parseAndSetParameter(value, op, reader);
break;
}
case CIPHER_SUITES: {
JSSEResourceDefinition.CIPHER_SUITES.parseAndSetParameter(value, op, reader);
break;
}
case PROTOCOLS: {
JSSEResourceDefinition.PROTOCOLS.parseAndSetParameter(value, op, reader);
break;
}
default:
throw unexpectedAttribute(reader, i);
}
}
if (!visited.containsAll(required)) {
throw SecurityLogger.ROOT_LOGGER.xmlStreamExceptionMissingAttribute(Attribute.KEYSTORE_PASSWORD.getLocalName(),
Attribute.TRUSTSTORE_PASSWORD.getLocalName(), reader.getLocation());
}
parseProperties(Element.PROPERTY.getLocalName(), reader, op, JSSEResourceDefinition.ADDITIONAL_PROPERTIES);
}
}