/*
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.switchyard.as7.extension;
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.SUBSYSTEM;
import static org.jboss.as.controller.parsing.ParseUtils.missingRequired;
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.switchyard.as7.extension.CommonAttributes.EXTENSION;
import static org.switchyard.as7.extension.CommonAttributes.IMPLCLASS;
import static org.switchyard.as7.extension.CommonAttributes.MODULE;
import static org.switchyard.as7.extension.CommonAttributes.PROPERTIES;
import static org.switchyard.as7.extension.CommonAttributes.SECURITY_CONFIG;
import static org.switchyard.as7.extension.CommonAttributes.SOCKET_BINDING;
import java.util.Collections;
import java.util.List;
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.descriptions.ModelDescriptionConstants;
import org.jboss.dmr.ModelNode;
import org.jboss.staxmapper.XMLElementReader;
import org.jboss.staxmapper.XMLExtendedStreamReader;
/**
* A SwitchYard subsystem reader/parser.
*
* @author Magesh Kumar B <mageshbk@jboss.com> (C) 2012 Red Hat Inc.
*/
final class SwitchYardSubsystemReader implements XMLStreamConstants, XMLElementReader<List<ModelNode>> {
private static final SwitchYardSubsystemReader INSTANCE = new SwitchYardSubsystemReader();
private SwitchYardSubsystemReader() {
// forbidden instantiation
}
static SwitchYardSubsystemReader getInstance() {
return INSTANCE;
}
/** {@inheritDoc} */
@Override
public void readElement(final XMLExtendedStreamReader reader, List<ModelNode> list) throws XMLStreamException {
// Require no attributes
requireNoAttributes(reader);
// Add our subsystem's 'add' operation
ModelNode subsystem = SwitchYardExtension.createAddSubsystemOperation();
list.add(subsystem);
// Elements
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
if (reader.getNamespaceURI().equals(SwitchYardExtension.NAMESPACE)) {
final Element element = Element.forName(reader.getLocalName());
switch (element) {
case SOCKET_BINDING:
String sockets = null;
final int count = reader.getAttributeCount();
for (int i = 0; i < count; i++) {
requireNoNamespaceAttribute(reader, i);
final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i));
switch (attribute) {
case NAMES:
sockets = reader.getAttributeValue(i);
break;
default:
throw unexpectedAttribute(reader, i);
}
}
if (sockets != null) {
subsystem.get(SOCKET_BINDING).set(sockets);
}
requireNoContent(reader);
break;
case SECURITY_CONFIGS:
parseSecurityConfigsElement(reader, list);
break;
case MODULES:
parseModulesElement(reader, list);
break;
case EXTENSIONS:
parseExtensionsElement(reader, list);
break;
case PROPERTIES:
ModelNode properties = parsePropertiesElement("", reader);
if (properties != null) {
subsystem.get(PROPERTIES).set(properties);
}
break;
default:
throw unexpectedElement(reader);
}
}
}
}
void parseSecurityConfigsElement(XMLExtendedStreamReader reader, List<ModelNode> list) throws XMLStreamException {
// Handle attributes
requireNoAttributes(reader);
// Handle module elements
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
if (reader.getNamespaceURI().equals(SwitchYardExtension.NAMESPACE)) {
final Element element = Element.forName(reader.getLocalName());
if (element == Element.SECURITY_CONFIG) {
parseSecurityConfigElement(reader, list);
} else {
throw unexpectedElement(reader);
}
}
}
}
void parseSecurityConfigElement(XMLExtendedStreamReader reader, List<ModelNode> list) throws XMLStreamException {
String identifier = null;
final int count = reader.getAttributeCount();
for (int i = 0; i < count; i++) {
requireNoNamespaceAttribute(reader, i);
final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i));
switch (attribute) {
case IDENTIFIER:
identifier = reader.getAttributeValue(i);
break;
default:
throw unexpectedAttribute(reader, i);
}
}
if (identifier == null) {
throw missingRequired(reader, Collections.singleton(Attribute.IDENTIFIER));
}
//Add the 'add' operation for each 'security-config' child
ModelNode securityConfigAdd = new ModelNode();
securityConfigAdd.get(OP).set(ModelDescriptionConstants.ADD);
PathAddress addr = PathAddress.pathAddress(PathElement.pathElement(SUBSYSTEM, SwitchYardExtension.SUBSYSTEM_NAME), PathElement.pathElement(SECURITY_CONFIG, identifier));
securityConfigAdd.get(OP_ADDR).set(addr.toModelNode());
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
final Element element1 = Element.forName(reader.getLocalName());
switch (element1) {
case PROPERTIES:
ModelNode properties = parsePropertiesElement(identifier, reader);
if (properties != null) {
securityConfigAdd.get(PROPERTIES).set(properties);
}
break;
default:
throw unexpectedElement(reader);
}
}
list.add(securityConfigAdd);
}
void parseModulesElement(XMLExtendedStreamReader reader, List<ModelNode> list) throws XMLStreamException {
// Handle attributes
requireNoAttributes(reader);
// Handle module elements
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
if (reader.getNamespaceURI().equals(SwitchYardExtension.NAMESPACE)) {
final Element element = Element.forName(reader.getLocalName());
if (element == Element.MODULE) {
parseModuleElement(reader, list);
} else {
throw unexpectedElement(reader);
}
}
}
}
void parseModuleElement(XMLExtendedStreamReader reader, List<ModelNode> list) throws XMLStreamException {
String identifier = null;
String implClass = null;
final int count = reader.getAttributeCount();
for (int i = 0; i < count; i++) {
requireNoNamespaceAttribute(reader, i);
final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i));
switch (attribute) {
case IDENTIFIER:
identifier = reader.getAttributeValue(i);
break;
case IMPLCLASS:
implClass = reader.getAttributeValue(i);
break;
default:
throw unexpectedAttribute(reader, i);
}
}
if (identifier == null) {
throw missingRequired(reader, Collections.singleton(Attribute.IDENTIFIER));
}
if (implClass == null) {
throw missingRequired(reader, Collections.singleton(Attribute.IMPLCLASS));
}
//Add the 'add' operation for each 'module' child
ModelNode moduleAdd = new ModelNode();
moduleAdd.get(OP).set(ModelDescriptionConstants.ADD);
PathAddress addr = PathAddress.pathAddress(PathElement.pathElement(SUBSYSTEM, SwitchYardExtension.SUBSYSTEM_NAME), PathElement.pathElement(MODULE, identifier));
moduleAdd.get(OP_ADDR).set(addr.toModelNode());
moduleAdd.get(IMPLCLASS).set(implClass);
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
final Element element1 = Element.forName(reader.getLocalName());
switch (element1) {
case PROPERTIES:
ModelNode properties = parsePropertiesElement(identifier, reader);
if (properties != null) {
moduleAdd.get(PROPERTIES).set(properties);
}
break;
default:
throw unexpectedElement(reader);
}
}
list.add(moduleAdd);
}
ModelNode parsePropertiesElement(String identifier, XMLExtendedStreamReader reader) throws XMLStreamException {
// Handle attributes
requireNoAttributes(reader);
ModelNode properties = new ModelNode();
StringBuffer configModel = new StringBuffer();
// Handle elements
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
if (reader.getNamespaceURI().equals(SwitchYardExtension.NAMESPACE)) {
final Element element = Element.forName(reader.getLocalName());
String name = reader.getLocalName();
String value = reader.getElementText();
if (properties.has(name)) {
throw ExtensionMessages.MESSAGES.alreadyDeclared(element.getLocalName(), reader.getLocation().toString());
}
ModelNode property = new ModelNode();
property.set(value);
properties.get(name).set(property);
configModel.append(element.toString());
}
}
return properties;
}
void parseExtensionsElement(XMLExtendedStreamReader reader, List<ModelNode> list) throws XMLStreamException {
// Handle attributes
requireNoAttributes(reader);
// Handle module elements
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
if (reader.getNamespaceURI().equals(SwitchYardExtension.NAMESPACE)) {
final Element element = Element.forName(reader.getLocalName());
if (element == Element.EXTENSION) {
parseExtensionElement(reader, list);
} else {
throw unexpectedElement(reader);
}
}
}
}
void parseExtensionElement(XMLExtendedStreamReader reader, List<ModelNode> list) throws XMLStreamException {
String identifier = null;
final int count = reader.getAttributeCount();
for (int i = 0; i < count; i++) {
requireNoNamespaceAttribute(reader, i);
final Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i));
switch (attribute) {
case IDENTIFIER:
identifier = reader.getAttributeValue(i);
break;
default:
throw unexpectedAttribute(reader, i);
}
}
if (identifier == null) {
throw missingRequired(reader, Collections.singleton(Attribute.IDENTIFIER));
}
//Add the 'add' operation for each 'module' child
ModelNode moduleAdd = new ModelNode();
moduleAdd.get(OP).set(ModelDescriptionConstants.ADD);
PathAddress addr = PathAddress.pathAddress(PathElement.pathElement(SUBSYSTEM, SwitchYardExtension.SUBSYSTEM_NAME), PathElement.pathElement(EXTENSION, identifier));
moduleAdd.get(OP_ADDR).set(addr.toModelNode());
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
throw unexpectedElement(reader);
}
list.add(moduleAdd);
}
}