All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xnio.XnioXmlParser Maven / Gradle / Ivy

There is a newer version: 3.8.16.Final
Show newest version
/*
 * JBoss, Home of Professional Open Source
 *
 * Copyright 2017 Red Hat, Inc. and/or its affiliates.
 *
 * 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.xnio;

import static javax.xml.stream.XMLStreamConstants.*;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Collections;

import org.wildfly.client.config.ClientConfiguration;
import org.wildfly.client.config.ConfigXMLParseException;
import org.wildfly.client.config.ConfigurationXMLStreamReader;
import org.wildfly.common.net.CidrAddress;

/**
 * The XNIO XML configuration parser.
 *
 * @author David M. Lloyd
 */
final class XnioXmlParser {

    private static final String NS_XNIO_3_5 = "urn:xnio:3.5";

    static XnioWorker parseWorker(Xnio xnio) throws ConfigXMLParseException, IOException {
        return parseWorker(xnio, ClientConfiguration.getInstance());
    }

    static XnioWorker parseWorker(Xnio xnio, ClientConfiguration clientConfiguration) throws ConfigXMLParseException, IOException {
        final XnioWorker.Builder builder = xnio.createWorkerBuilder();
        if (clientConfiguration == null) {
            return null;
        }
        builder.setDaemon(true);
        final ConfigurationXMLStreamReader reader = clientConfiguration.readConfiguration(Collections.singleton(NS_XNIO_3_5));

        parseDocument(reader, builder);

        return builder.build();
    }

    private static void parseDocument(final ConfigurationXMLStreamReader reader, final XnioWorker.Builder workerBuilder) throws ConfigXMLParseException {
        if (reader.hasNext()) switch (reader.nextTag()) {
            case START_ELEMENT: {
                checkElementNamespace(reader);
                switch (reader.getLocalName()) {
                    case "worker": {
                        parseWorkerElement(reader, workerBuilder);
                        break;
                    }
                    default: throw reader.unexpectedElement();
                }
                break;
            }
            default: {
                throw reader.unexpectedContent();
            }
        }
    }

    private static void parseWorkerElement(final ConfigurationXMLStreamReader reader, final XnioWorker.Builder workerBuilder) throws ConfigXMLParseException {
        requireNoAttributes(reader);
        int foundBits = 0;

        while (reader.hasNext()) {
            switch (reader.nextTag()) {
                case END_ELEMENT: {
                    return;
                }
                case START_ELEMENT: {
                    checkElementNamespace(reader);
                    switch (reader.getLocalName()) {
                        case "daemon-threads": {
                            if (isSet(foundBits, 0)) throw reader.unexpectedElement();
                            foundBits = setBit(foundBits, 0);
                            parseDaemonThreads(reader, workerBuilder);
                            break;
                        }
                        case "worker-name": {
                            if (isSet(foundBits, 1)) throw reader.unexpectedElement();
                            foundBits = setBit(foundBits, 1);
                            parseWorkerName(reader, workerBuilder);
                            break;
                        }
                        case "pool-size": {
                            if (isSet(foundBits, 2)) throw reader.unexpectedElement();
                            foundBits = setBit(foundBits, 2);
                            parsePoolSize(reader, workerBuilder);
                            break;
                        }
                        case "task-keepalive": {
                            if (isSet(foundBits, 3)) throw reader.unexpectedElement();
                            foundBits = setBit(foundBits, 3);
                            parseTaskKeepalive(reader, workerBuilder);
                            break;
                        }
                        case "io-threads": {
                            if (isSet(foundBits, 4)) throw reader.unexpectedElement();
                            foundBits = setBit(foundBits, 4);
                            parseIoThreads(reader, workerBuilder);
                            break;
                        }
                        case "stack-size": {
                            if (isSet(foundBits, 5)) throw reader.unexpectedElement();
                            foundBits = setBit(foundBits, 5);
                            parseStackSize(reader, workerBuilder);
                            break;
                        }
                        case "outbound-bind-addresses": {
                            if (isSet(foundBits, 6)) throw reader.unexpectedElement();
                            foundBits = setBit(foundBits, 6);
                            parseOutboundBindAddresses(reader, workerBuilder);
                            break;
                        }
                        default: {
                            throw reader.unexpectedElement();
                        }
                    }
                }
            }
        }
        throw reader.unexpectedDocumentEnd();
    }

    private static void parseDaemonThreads(final ConfigurationXMLStreamReader reader, final XnioWorker.Builder workerBuilder) throws ConfigXMLParseException {
        requireSingleAttribute(reader, "value");
        final boolean daemon = reader.getBooleanAttributeValueResolved(0);
        if (! reader.hasNext()) throw reader.unexpectedDocumentEnd();
        if (reader.nextTag() != END_ELEMENT) throw reader.unexpectedElement();
        workerBuilder.setDaemon(daemon);
        return;
    }

    private static void parseWorkerName(final ConfigurationXMLStreamReader reader, final XnioWorker.Builder workerBuilder) throws ConfigXMLParseException {
        requireSingleAttribute(reader, "value");
        String name = reader.getAttributeValueResolved(0);
        if (! reader.hasNext()) throw reader.unexpectedDocumentEnd();
        if (reader.nextTag() != END_ELEMENT) throw reader.unexpectedElement();
        workerBuilder.setWorkerName(name);
        return;
    }

    private static void parsePoolSize(final ConfigurationXMLStreamReader reader, final XnioWorker.Builder workerBuilder) throws ConfigXMLParseException {
        requireSingleAttribute(reader, "max-threads");
        int threadCount = reader.getIntAttributeValueResolved(0);
        if (! reader.hasNext()) throw reader.unexpectedDocumentEnd();
        if (reader.nextTag() != END_ELEMENT) throw reader.unexpectedElement();
        workerBuilder.setCoreWorkerPoolSize(threadCount);
        workerBuilder.setMaxWorkerPoolSize(threadCount);
        return;
    }

    private static void parseTaskKeepalive(final ConfigurationXMLStreamReader reader, final XnioWorker.Builder workerBuilder) throws ConfigXMLParseException {
        requireSingleAttribute(reader, "value");
        int duration = reader.getIntAttributeValueResolved(0);
        if (! reader.hasNext()) throw reader.unexpectedDocumentEnd();
        if (reader.nextTag() != END_ELEMENT) throw reader.unexpectedElement();
        workerBuilder.setWorkerKeepAlive(duration);
        return;
    }

    private static void parseIoThreads(final ConfigurationXMLStreamReader reader, final XnioWorker.Builder workerBuilder) throws ConfigXMLParseException {
        requireSingleAttribute(reader, "value");
        int threadCount = reader.getIntAttributeValueResolved(0);
        if (! reader.hasNext()) throw reader.unexpectedDocumentEnd();
        if (reader.nextTag() != END_ELEMENT) throw reader.unexpectedElement();
        workerBuilder.setWorkerIoThreads(threadCount);
        return;
    }

    private static void parseStackSize(final ConfigurationXMLStreamReader reader, final XnioWorker.Builder workerBuilder) throws ConfigXMLParseException {
        requireSingleAttribute(reader, "value");
        long stackSize = reader.getLongAttributeValueResolved(0);
        if (! reader.hasNext()) throw reader.unexpectedDocumentEnd();
        if (reader.nextTag() != END_ELEMENT) throw reader.unexpectedElement();
        workerBuilder.setWorkerStackSize(stackSize);
        return;
    }

    private static void parseOutboundBindAddresses(final ConfigurationXMLStreamReader reader, final XnioWorker.Builder workerBuilder) throws ConfigXMLParseException {
        requireNoAttributes(reader);
        for (;;) {
            if (! reader.hasNext()) throw reader.unexpectedDocumentEnd();
            if (reader.nextTag() == START_ELEMENT) {
                checkElementNamespace(reader);
                if (! reader.getLocalName().equals("bind-address")) {
                    throw reader.unexpectedElement();
                }
                parseBindAddress(reader, workerBuilder);
            } else {
                assert reader.getEventType() == END_ELEMENT;
                return;
            }
        }
    }

    private static void parseBindAddress(final ConfigurationXMLStreamReader reader, final XnioWorker.Builder workerBuilder) throws ConfigXMLParseException {
        final int cnt = reader.getAttributeCount();
        InetAddress address = null;
        int port = 0;
        CidrAddress match = null;
        for (int i = 0; i < cnt; i ++) {
            checkAttributeNamespace(reader, i);
            switch (reader.getAttributeLocalName(i)) {
                case "match": {
                    match = reader.getCidrAddressAttributeValueResolved(i);
                    break;
                }
                case "bind-address": {
                    address = reader.getInetAddressAttributeValueResolved(i);
                    break;
                }
                case "bind-port": {
                    port = reader.getIntAttributeValueResolved(i, 0, 65535);
                    break;
                }
                default: {
                    throw reader.unexpectedAttribute(i);
                }
            }
        }
        if (match == null) throw reader.missingRequiredAttribute(null, "match");
        if (address == null) throw reader.missingRequiredAttribute(null, "bind-address");
        workerBuilder.addBindAddressConfiguration(match, new InetSocketAddress(address, port));
        if (! reader.hasNext()) throw reader.unexpectedDocumentEnd();
        if (reader.nextTag() != END_ELEMENT) throw reader.unexpectedElement();
    }

    private static void checkElementNamespace(final ConfigurationXMLStreamReader reader) throws ConfigXMLParseException {
        if (! reader.getNamespaceURI().equals(NS_XNIO_3_5)) {
            throw reader.unexpectedElement();
        }
    }

    private static void checkAttributeNamespace(final ConfigurationXMLStreamReader reader, final int idx) throws ConfigXMLParseException {
        final String attributeNamespace = reader.getAttributeNamespace(idx);
        if (attributeNamespace != null && ! attributeNamespace.isEmpty()) {
            throw reader.unexpectedAttribute(idx);
        }
    }

    private static void requireNoAttributes(final ConfigurationXMLStreamReader reader) throws ConfigXMLParseException {
        final int attributeCount = reader.getAttributeCount();
        if (attributeCount > 0) {
            throw reader.unexpectedAttribute(0);
        }
    }

    private static void requireSingleAttribute(final ConfigurationXMLStreamReader reader, final String attributeName) throws ConfigXMLParseException {
        final int attributeCount = reader.getAttributeCount();
        if (attributeCount < 1) {
            throw reader.missingRequiredAttribute("", attributeName);
        }
        checkAttributeNamespace(reader, 0);
        if (! reader.getAttributeLocalName(0).equals(attributeName)) {
            throw reader.unexpectedAttribute(0);
        }
        if (attributeCount > 1) {
            throw reader.unexpectedAttribute(1);
        }
    }

    private static boolean isSet(int var, int bit) {
        return (var & 1 << bit) != 0;
    }

    private static int setBit(int var, int bit) {
        return var | 1 << bit;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy