org.wildfly.discovery.DiscoveryXmlParser Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including
all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and
JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
The newest version!
/*
* JBoss, Home of Professional Open Source.
* Copyright 2016 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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.wildfly.discovery;
import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import org.jboss.modules.Module;
import org.jboss.modules.ModuleLoadException;
import org.wildfly.client.config.ClientConfiguration;
import org.wildfly.client.config.ConfigXMLParseException;
import org.wildfly.client.config.ConfigurationXMLStreamReader;
import org.wildfly.common.Assert;
import org.wildfly.discovery.impl.AggregateDiscoveryProvider;
import org.wildfly.discovery.impl.AggregateRegistryProvider;
import org.wildfly.discovery.impl.LocalRegistryAndDiscoveryProvider;
import org.wildfly.discovery.impl.StaticDiscoveryProvider;
import org.wildfly.discovery.spi.DiscoveryProvider;
import org.wildfly.discovery.spi.ExternalDiscoveryConfigurator;
import org.wildfly.discovery.spi.RegistryProvider;
/**
* @author David M. Lloyd
*/
final class DiscoveryXmlParser {
private static final DiscoveryProvider[] NO_DISCOVERY_PROVIDERS = new DiscoveryProvider[0];
private static final RegistryProvider[] NO_REGISTRY_PROVIDERS = new RegistryProvider[0];
private DiscoveryXmlParser() {
}
static final String NS_DISCOVERY_1_0 = "urn:wildfly-discovery:1.0";
static ConfiguredProvider getConfiguredProvider() {
List discoveryProviders = new ArrayList<>();
List registryProviders = new ArrayList<>();
final ClientConfiguration clientConfiguration = ClientConfiguration.getInstance();
if (clientConfiguration != null) try (final ConfigurationXMLStreamReader streamReader = clientConfiguration.readConfiguration(Collections.singleton(NS_DISCOVERY_1_0))) {
parseConfiguration(streamReader, discoveryProviders, registryProviders);
} catch (ConfigXMLParseException e) {
throw new InvalidDiscoveryConfigurationException(e);
}
ServiceLoader loader = ServiceLoader.load(ExternalDiscoveryConfigurator.class);
final Iterator iterator = loader.iterator();
for (;;) try {
if (! iterator.hasNext()) break;
final ExternalDiscoveryConfigurator configurator = iterator.next();
configurator.configure(
provider -> discoveryProviders.add(Assert.checkNotNullParam("provider", provider)),
provider -> registryProviders.add(Assert.checkNotNullParam("provider", provider))
);
} catch (ServiceConfigurationError | RuntimeException e) {
// TODO log & continue
}
final DiscoveryProvider discoveryProvider;
if (discoveryProviders.isEmpty()) {
discoveryProvider = DiscoveryProvider.EMPTY;
} else if (discoveryProviders.size() == 1) {
discoveryProvider = discoveryProviders.get(0);
} else {
discoveryProvider = new AggregateDiscoveryProvider(discoveryProviders.toArray(NO_DISCOVERY_PROVIDERS));
}
final RegistryProvider registryProvider;
if (registryProviders.isEmpty()) {
registryProvider = RegistryProvider.EMPTY;
} else if (registryProviders.size() == 1) {
registryProvider = registryProviders.get(0);
} else {
registryProvider = new AggregateRegistryProvider(registryProviders.toArray(NO_REGISTRY_PROVIDERS));
}
return new ConfiguredProvider(discoveryProvider, registryProvider);
}
private static void parseConfiguration(final ConfigurationXMLStreamReader reader, final List discoveryProviders, final List registryProviders) throws ConfigXMLParseException {
if (reader.hasNext()) {
final int tag = reader.nextTag();
switch (tag) {
case START_ELEMENT: {
checkNamespace(reader);
switch (reader.getLocalName()) {
case "discovery": {
parseDiscoveryElement(reader, discoveryProviders, registryProviders);
return;
}
default: {
throw reader.unexpectedElement();
}
}
}
default: {
throw reader.unexpectedContent();
}
}
}
}
private static void parseDiscoveryElement(final ConfigurationXMLStreamReader reader, final List discoveryProviders, final List registryProviders) throws ConfigXMLParseException {
DiscoveryProvider discoveryProvider = DiscoveryProvider.EMPTY;
RegistryProvider registryProvider = RegistryProvider.EMPTY;
LocalRegistryAndDiscoveryProvider localRegistry = new LocalRegistryAndDiscoveryProvider();
requireNoAttributes(reader);
out: while (reader.hasNext()) {
int tag = reader.nextTag();
switch (tag) {
case START_ELEMENT: {
checkNamespace(reader);
switch (reader.getLocalName()) {
case "discovery-provider": {
if (discoveryProvider != DiscoveryProvider.EMPTY) {
throw reader.unexpectedElement();
}
discoveryProviders.add(parseDiscoveryProvider(reader, localRegistry));
break;
}
case "registry-provider": {
if (registryProvider != RegistryProvider.EMPTY) {
throw reader.unexpectedElement();
}
registryProviders.add(parseRegistryProvider(reader, localRegistry));
break;
}
default: {
throw reader.unexpectedElement();
}
}
break;
}
case END_ELEMENT: {
break out;
}
}
}
}
private static RegistryProvider parseRegistryProvider(final ConfigurationXMLStreamReader reader, final LocalRegistryAndDiscoveryProvider localRegistry) throws ConfigXMLParseException {
requireNoAttributes(reader);
RegistryProvider registryProvider;
final int tag = reader.nextTag();
switch (tag) {
case START_ELEMENT: {
checkNamespace(reader);
switch (reader.getLocalName()) {
case "local-registry": {
registryProvider = localRegistry;
expectEnd(reader);
break;
}
case "aggregate": {
registryProvider = parseAggregateRegistry(reader, localRegistry);
break;
}
case "custom": {
registryProvider = parseCustom(reader, RegistryProvider.class);
break;
}
default: {
throw reader.unexpectedElement();
}
}
expectEnd(reader);
return registryProvider;
}
default: {
throw reader.unexpectedElement();
}
}
}
private static DiscoveryProvider parseDiscoveryProvider(final ConfigurationXMLStreamReader reader, final LocalRegistryAndDiscoveryProvider localRegistry) throws ConfigXMLParseException {
requireNoAttributes(reader);
DiscoveryProvider discoveryProvider;
final int tag = reader.nextTag();
switch (tag) {
case START_ELEMENT: {
checkNamespace(reader);
switch (reader.getLocalName()) {
case "local-registry": {
discoveryProvider = localRegistry;
expectEnd(reader);
break;
}
case "static": {
discoveryProvider = parseStatic(reader);
break;
}
case "aggregate": {
discoveryProvider = parseAggregateDiscovery(reader, localRegistry);
break;
}
case "custom": {
discoveryProvider = parseCustom(reader, DiscoveryProvider.class);
break;
}
default: {
throw reader.unexpectedElement();
}
}
expectEnd(reader);
return discoveryProvider;
}
}
throw reader.missingRequiredElement(NS_DISCOVERY_1_0, "local-registry/static/aggregate/custom");
}
private static DiscoveryProvider parseAggregateDiscovery(final ConfigurationXMLStreamReader reader, final LocalRegistryAndDiscoveryProvider localRegistry) throws ConfigXMLParseException {
requireNoAttributes(reader);
final List delegates = new ArrayList<>();
out: while (reader.hasNext()) {
final int tag = reader.nextTag();
switch (tag) {
case START_ELEMENT: {
checkNamespace(reader);
switch (reader.getLocalName()) {
case "discovery-provider": {
delegates.add(parseDiscoveryProvider(reader, localRegistry));
break;
}
default: {
throw reader.unexpectedElement();
}
}
}
case END_ELEMENT: {
break out;
}
}
}
return new AggregateDiscoveryProvider(delegates.toArray(NO_DISCOVERY_PROVIDERS));
}
private static RegistryProvider parseAggregateRegistry(final ConfigurationXMLStreamReader reader, final LocalRegistryAndDiscoveryProvider localRegistry) throws ConfigXMLParseException {
requireNoAttributes(reader);
final List delegates = new ArrayList<>();
out: while (reader.hasNext()) {
final int tag = reader.nextTag();
switch (tag) {
case START_ELEMENT: {
checkNamespace(reader);
switch (reader.getLocalName()) {
case "registry-provider": {
delegates.add(parseRegistryProvider(reader, localRegistry));
break;
}
default: {
throw reader.unexpectedElement();
}
}
}
case END_ELEMENT: {
break out;
}
}
}
return new AggregateRegistryProvider(delegates.toArray(NO_REGISTRY_PROVIDERS));
}
private static DiscoveryProvider parseStatic(final ConfigurationXMLStreamReader reader) throws ConfigXMLParseException {
List serviceURLs = new ArrayList<>();
requireNoAttributes(reader);
out: while (reader.hasNext()) {
final int tag = reader.nextTag();
switch (tag) {
case START_ELEMENT: {
checkNamespace(reader);
switch (reader.getLocalName()) {
case "service": {
serviceURLs.add(parseService(reader));
break;
}
default: {
throw reader.unexpectedElement();
}
}
break;
}
case END_ELEMENT: {
break out;
}
}
}
return new StaticDiscoveryProvider(serviceURLs);
}
private static void requireNoAttributes(final ConfigurationXMLStreamReader reader) throws ConfigXMLParseException {
if (reader.getAttributeCount() > 0) {
throw reader.unexpectedAttribute(0);
}
}
private static ServiceURL parseService(final ConfigurationXMLStreamReader reader) throws ConfigXMLParseException {
final ServiceURL.Builder builder = new ServiceURL.Builder();
URI uri = null;
String uriSchemeAuthority = null;
String abstractType = null;
String abstractTypeAuthority = null;
int cnt = reader.getAttributeCount();
for (int i = 0; i < cnt; i ++) {
checkAttributeNamespace(reader, i);
switch (reader.getAttributeLocalName(i)) {
case "uri": {
uri = reader.getURIAttributeValueResolved(i);
break;
}
case "uri-scheme-authority": {
uriSchemeAuthority = reader.getAttributeValueResolved(i);
break;
}
case "abstract-type": {
abstractType = reader.getAttributeValueResolved(i);
break;
}
case "abstract-type-authority": {
abstractTypeAuthority = reader.getAttributeValueResolved(i);
break;
}
default: {
throw reader.unexpectedAttribute(i);
}
}
}
if (uri == null) {
throw reader.missingRequiredAttribute(null, "uri");
}
builder.setUri(uri);
if (uriSchemeAuthority != null) builder.setUriSchemeAuthority(uriSchemeAuthority);
if (abstractType != null) builder.setAbstractType(abstractType);
if (abstractTypeAuthority != null) builder.setAbstractTypeAuthority(abstractTypeAuthority);
out: while (reader.hasNext()) {
final int tag = reader.nextTag();
switch (tag) {
case START_ELEMENT: {
checkNamespace(reader);
switch (reader.getLocalName()) {
case "attribute": {
parseAttribute(reader, builder);
break;
}
default: {
throw reader.unexpectedElement();
}
}
break;
}
case END_ELEMENT: {
break out;
}
}
}
return builder.create();
}
private static void checkAttributeNamespace(final ConfigurationXMLStreamReader reader, final int i) throws ConfigXMLParseException {
if (reader.getAttributeNamespace(i) != null) {
throw reader.unexpectedAttribute(i);
}
}
private static void parseAttribute(final ConfigurationXMLStreamReader reader, final ServiceURL.Builder builder) throws ConfigXMLParseException {
String name = null;
AttributeValue value = null;
int cnt = reader.getAttributeCount();
for (int i = 0; i < cnt; i ++) {
checkAttributeNamespace(reader, i);
switch (reader.getAttributeLocalName(i)) {
case "name": {
name = reader.getAttributeValueResolved(i);
break;
}
case "value": {
value = AttributeValue.fromString(reader.getAttributeValueResolved(i));
break;
}
default: {
throw reader.unexpectedAttribute(i);
}
}
}
if (name == null) {
throw reader.missingRequiredAttribute(null, "name");
}
expectEnd(reader);
if (value == null) {
builder.addAttribute(name);
} else {
builder.addAttribute(name, value);
}
}
private static void checkNamespace(final ConfigurationXMLStreamReader reader) throws ConfigXMLParseException {
switch (reader.getNamespaceURI()) {
case NS_DISCOVERY_1_0:
break;
default:
throw reader.unexpectedElement();
}
}
private static T parseCustom(final ConfigurationXMLStreamReader reader, final Class type) throws ConfigXMLParseException {
String className = null;
String moduleName = null;
int cnt = reader.getAttributeCount();
for (int i = 0; i < cnt; i ++) {
checkAttributeNamespace(reader, i);
switch (reader.getAttributeLocalName(i)) {
case "class": {
className = reader.getAttributeValueResolved(i);
break;
}
case "module": {
moduleName = reader.getAttributeValueResolved(i);
break;
}
default: {
throw reader.unexpectedAttribute(i);
}
}
}
T item;
if (moduleName != null) {
item = ModuleLoadDelegate.loadService(moduleName, className, type);
} else {
if (className != null) try {
item = Class.forName(className, true, DiscoveryXmlParser.class.getClassLoader()).asSubclass(type).newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
throw new InvalidDiscoveryConfigurationException(e);
}
else {
final ServiceLoader loader = ServiceLoader.load(type);
final Iterator iterator = loader.iterator();
try {
if (! iterator.hasNext()) {
throw new InvalidDiscoveryConfigurationException("No provider found");
}
item = iterator.next();
} catch (ServiceConfigurationError e) {
throw new InvalidDiscoveryConfigurationException(e);
}
}
}
expectEnd(reader);
return item;
}
static final class ModuleLoadDelegate {
static T loadService(String moduleName, String className, final Class type) throws ConfigXMLParseException {
if (className != null) {
try {
Module.loadClassFromCallerModuleLoader(moduleName, className).asSubclass(type).newInstance();
} catch (ModuleLoadException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
throw new InvalidDiscoveryConfigurationException(e);
}
} else {
try {
final ServiceLoader loader = Module.loadServiceFromCallerModuleLoader(moduleName, type);
final Iterator iterator = loader.iterator();
try {
if (!iterator.hasNext()) {
throw new InvalidDiscoveryConfigurationException("No provider found in module " + moduleName);
}
return iterator.next();
} catch (ServiceConfigurationError e) {
throw new InvalidDiscoveryConfigurationException(e);
}
} catch (ModuleLoadException e) {
throw new InvalidDiscoveryConfigurationException(e);
}
}
return null;
}
}
private static void expectEnd(final ConfigurationXMLStreamReader reader) throws ConfigXMLParseException {
if (reader.nextTag() != END_ELEMENT) {
throw reader.unexpectedElement();
}
}
}