/**
* Copyright 2015-2016 Red Hat, Inc, and individual 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.wildfly.swarm.container.runtime.xmlconfig;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.ServiceLoader;
import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import javax.xml.namespace.QName;
import org.jboss.as.controller.Extension;
import org.jboss.as.controller.ProcessType;
import org.jboss.as.controller.RunningMode;
import org.jboss.as.controller.parsing.ExtensionParsingContext;
import org.jboss.as.controller.parsing.ProfileParsingCompletionHandler;
import org.jboss.dmr.ModelNode;
import org.jboss.modules.Module;
import org.jboss.modules.ModuleIdentifier;
import org.jboss.staxmapper.XMLElementReader;
import org.wildfly.swarm.bootstrap.performance.Performance;
import org.wildfly.swarm.internal.SwarmConfigMessages;
import org.wildfly.swarm.internal.SwarmMessages;
import org.wildfly.swarm.spi.api.Fraction;
import org.wildfly.swarm.spi.api.annotations.WildFlyExtension;
/**
* Produces an XML configuration (standalone.xml) parser for available fractions.
*
* @author Bob McWhirter
*/
@ApplicationScoped
public class StandaloneXMLParserProducer {
@Inject
private Instance<Fraction> fractions;
private StandaloneXMLParser parser = new StandaloneXMLParser();
@PostConstruct
public void setupFactories() throws Exception {
for (Fraction fraction : this.fractions) {
setupFactory(fraction);
}
}
@Produces
@ApplicationScoped
StandaloneXMLParser standaloneXmlParser() {
return this.parser;
}
private void setupFactory(Fraction fraction) throws Exception {
try (AutoCloseable handle = Performance.time("Setting up XML parser: " + fraction.getClass().getSimpleName())) {
WildFlyExtension anno = fraction.getClass().getAnnotation(WildFlyExtension.class);
if (anno == null) {
return;
}
String extensionModuleName = anno.module();
String extensionClassName = anno.classname();
boolean noClass = anno.noClass();
if (extensionClassName != null && extensionClassName.trim().isEmpty()) {
extensionClassName = null;
}
Module extensionModule = Module.getBootModuleLoader().loadModule(ModuleIdentifier.create(extensionModuleName));
if (noClass) {
// ignore it all
} else if (extensionClassName != null) {
Class<?> extCls = extensionModule.getClassLoader().loadClass(extensionClassName);
try {
Extension ext = (Extension) extCls.newInstance();
add(ext);
} catch (InstantiationException | IllegalAccessException e) {
SwarmConfigMessages.MESSAGES.errorCreatingExtension(extensionClassName, extensionModuleName, e);
}
} else {
ServiceLoader<Extension> extensionLoader = extensionModule.loadService(Extension.class);
Iterator<Extension> extensionIter = extensionLoader.iterator();
List<Extension> extensions = new ArrayList<>();
if (extensionIter.hasNext()) {
Extension ext = extensionIter.next();
extensions.add(ext);
}
if (extensions.size() > 1) {
throw SwarmMessages.MESSAGES.fractionHasMultipleExtensions(fraction.getClass().getName(), extensions.stream().map(Objects::toString).collect(Collectors.toList()));
}
if (!extensions.isEmpty()) {
add(extensions.get(0));
}
}
}
}
private void add(Extension ext) {
ParsingContext ctx = new ParsingContext();
ext.initializeParsers(ctx);
}
class ParsingContext implements ExtensionParsingContext {
@Override
public ProcessType getProcessType() {
return ProcessType.STANDALONE_SERVER;
}
@Override
public RunningMode getRunningMode() {
return RunningMode.NORMAL;
}
@Override
public void setSubsystemXmlMapping(String localName, String namespace, XMLElementReader<List<ModelNode>> parser) {
StandaloneXMLParserProducer.this.parser.addDelegate(new QName(namespace, "subsystem"), parser);
}
@Override
public void setProfileParsingCompletionHandler(ProfileParsingCompletionHandler profileParsingCompletionHandler) {
// ignore
}
}
}