org.jboss.as.server.moduleservice.ModuleResolvePhaseService Maven / Gradle / Ivy
package org.jboss.as.server.moduleservice;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.jboss.as.server.ServerMessages;
import org.jboss.as.server.deployment.module.ModuleDependency;
import org.jboss.modules.ModuleIdentifier;
import org.jboss.msc.inject.InjectionException;
import org.jboss.msc.inject.Injector;
import org.jboss.msc.service.Service;
import org.jboss.msc.service.ServiceBuilder;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.ServiceTarget;
import org.jboss.msc.service.StartContext;
import org.jboss.msc.service.StartException;
import org.jboss.msc.service.StopContext;
import static org.jboss.msc.service.ServiceBuilder.DependencyType.OPTIONAL;
import static org.jboss.msc.service.ServiceBuilder.DependencyType.REQUIRED;
/**
* Module phase resolve service. Basically this service attempts to resolve
* every dynamic transitive dependency of a module, and allows the module resolved service
* to start once this is complete.
*
* @author Stuart Douglas
*/
public class ModuleResolvePhaseService implements Service {
public static final ServiceName SERVICE_NAME = ServiceName.JBOSS.append("module", "resolve", "phase");
private final ModuleIdentifier moduleIdentifier;
private final Set alreadyResolvedModules;
private final int phaseNumber;
/**
* module specification that were resolved this phase. These are injected as the relevant spec services start.
*/
private final Set moduleSpecs = Collections.synchronizedSet(new HashSet());
public ModuleResolvePhaseService(final ModuleIdentifier moduleIdentifier, final Set alreadyResolvedModules, final int phaseNumber) {
this.moduleIdentifier = moduleIdentifier;
this.alreadyResolvedModules = alreadyResolvedModules;
this.phaseNumber = phaseNumber;
}
public ModuleResolvePhaseService(final ModuleIdentifier moduleIdentifier) {
this.moduleIdentifier = moduleIdentifier;
this.alreadyResolvedModules = Collections.emptySet();
this.phaseNumber = 0;
}
@Override
public void start(final StartContext startContext) throws StartException {
Set nextPhaseIdentifiers = new HashSet<>();
final Set nextAlreadySeen = new HashSet<>(alreadyResolvedModules);
for (final ModuleDefinition spec : moduleSpecs) {
if (spec != null) { //this can happen for optional dependencies
for (ModuleDependency dep : spec.getDependencies()) {
if (ServiceModuleLoader.isDynamicModule(dep.getIdentifier())) {
if (!alreadyResolvedModules.contains(dep.getIdentifier())) {
nextAlreadySeen.add(dep.getIdentifier());
nextPhaseIdentifiers.add(dep);
}
}
}
}
}
if (nextPhaseIdentifiers.isEmpty()) {
ServiceModuleLoader.installModuleResolvedService(startContext.getChildTarget(), moduleIdentifier);
} else {
installService(startContext.getChildTarget(), moduleIdentifier, phaseNumber + 1, nextPhaseIdentifiers, nextAlreadySeen);
}
}
public static void installService(final ServiceTarget serviceTarget, final ModuleDefinition moduleDefinition) {
final ModuleResolvePhaseService nextPhaseService = new ModuleResolvePhaseService(moduleDefinition.getModuleIdentifier(), Collections.singleton(moduleDefinition.getModuleIdentifier()), 0);
nextPhaseService.getModuleSpecs().add(moduleDefinition);
ServiceBuilder builder = serviceTarget.addService(moduleSpecServiceName(moduleDefinition.getModuleIdentifier(), 0), nextPhaseService);
builder.install();
}
private static void installService(final ServiceTarget serviceTarget, final ModuleIdentifier moduleIdentifier, int phaseNumber, final Set nextPhaseIdentifiers, final Set nextAlreadySeen) {
final ModuleResolvePhaseService nextPhaseService = new ModuleResolvePhaseService(moduleIdentifier, nextAlreadySeen, phaseNumber);
ServiceBuilder builder = serviceTarget.addService(moduleSpecServiceName(moduleIdentifier, phaseNumber), nextPhaseService);
for (ModuleDependency module : nextPhaseIdentifiers) {
builder.addDependency(module.isOptional() ? OPTIONAL : REQUIRED, ServiceModuleLoader.moduleSpecServiceName(module.getIdentifier()), ModuleDefinition.class, new Injector() {
ModuleDefinition definition;
@Override
public synchronized void inject(final ModuleDefinition o) throws InjectionException {
nextPhaseService.getModuleSpecs().add(o);
this.definition = o;
}
@Override
public synchronized void uninject() {
nextPhaseService.getModuleSpecs().remove(definition);
this.definition = null;
}
});
}
builder.install();
}
@Override
public void stop(final StopContext stopContext) {
}
@Override
public ModuleResolvePhaseService getValue() throws IllegalStateException, IllegalArgumentException {
return this;
}
public Set getModuleSpecs() {
return moduleSpecs;
}
public static ServiceName moduleSpecServiceName(ModuleIdentifier identifier, int phase) {
if (!ServiceModuleLoader.isDynamicModule(identifier)) {
ServerMessages.MESSAGES.missingModulePrefix(identifier, ServiceModuleLoader.MODULE_PREFIX);
}
return SERVICE_NAME.append(identifier.getName()).append(identifier.getSlot()).append("" + phase);
}
}