diff --git a/controller/src/main/java/org/jboss/as/controller/extension/ExtensionAddHandler.java b/controller/src/main/java/org/jboss/as/controller/extension/ExtensionAddHandler.java index 553ab2e8bef..c30bae4d6e5 100644 --- a/controller/src/main/java/org/jboss/as/controller/extension/ExtensionAddHandler.java +++ b/controller/src/main/java/org/jboss/as/controller/extension/ExtensionAddHandler.java @@ -87,7 +87,7 @@ public void handleRollback(OperationContext context, ModelNode operation) { }); } - void initializeExtension(String module, ManagementResourceRegistration rootRegistration) { + void initializeExtension(String module, ManagementResourceRegistration rootRegistration, PathAddress address) { initializeExtension(extensionRegistry, module, rootRegistration, extensionRegistryType); } @@ -110,7 +110,7 @@ static void initializeExtension(ExtensionRegistry extensionRegistry, String modu } while (extensions.hasNext()) { Extension extension = extensions.next(); - if (rootRegistration.enables(extension)) { + if (extensionRegistry.enables(extension)) { ClassLoader oldTccl = WildFlySecurityManager.setCurrentContextClassLoaderPrivileged(extension.getClass()); try { if (unknownModule || !extensionRegistry.getExtensionModuleNames().contains(module)) { @@ -121,7 +121,7 @@ static void initializeExtension(ExtensionRegistry extensionRegistry, String modu // now that we know the registry was unaware of the module unknownModule = true; } - extension.initialize(extensionRegistry.getExtensionContext(module, rootRegistration, extensionRegistryType)); + extension.initialize(extensionRegistry.getExtensionContext(module, extension.getStability(), rootRegistration, extensionRegistryType)); } finally { WildFlySecurityManager.setCurrentContextClassLoaderPrivileged(oldTccl); } diff --git a/controller/src/main/java/org/jboss/as/controller/extension/ExtensionRegistry.java b/controller/src/main/java/org/jboss/as/controller/extension/ExtensionRegistry.java index d8ef0102bb9..25dc77a1c18 100644 --- a/controller/src/main/java/org/jboss/as/controller/extension/ExtensionRegistry.java +++ b/controller/src/main/java/org/jboss/as/controller/extension/ExtensionRegistry.java @@ -39,11 +39,12 @@ import org.jboss.as.controller.PathElement; import org.jboss.as.controller.PersistentResourceXMLParser; import org.jboss.as.controller.ProcessType; +import org.jboss.as.controller.ProvidedResourceDefinition; import org.jboss.as.controller.ProxyController; import org.jboss.as.controller.ResourceDefinition; +import org.jboss.as.controller.ResourceRegistration; import org.jboss.as.controller.RunningMode; import org.jboss.as.controller.RunningModeControl; -import org.jboss.as.controller.SimpleResourceDefinition; import org.jboss.as.controller.SubsystemRegistration; import org.jboss.as.controller.access.Action; import org.jboss.as.controller.access.AuthorizationResult; @@ -81,6 +82,7 @@ import org.jboss.staxmapper.XMLElementReader; import org.jboss.staxmapper.XMLElementWriter; import org.jboss.staxmapper.XMLMapper; +import org.wildfly.common.Assert; import org.wildfly.common.function.Functions; import org.wildfly.security.auth.server.SecurityIdentity; @@ -361,7 +363,23 @@ public void initializeParsers(final Extension extension, final String moduleName * * @return the {@link ExtensionContext}. Will not return {@code null} */ + @Deprecated(forRemoval = true) public ExtensionContext getExtensionContext(final String moduleName, ManagementResourceRegistration rootRegistration, ExtensionRegistryType extensionRegistryType) { + return this.getExtensionContext(moduleName, Stability.DEFAULT, rootRegistration, extensionRegistryType); + } + + /** + * Gets an {@link ExtensionContext} for use when handling an {@code add} operation for + * a resource representing an {@link org.jboss.as.controller.Extension}. + * + * @param moduleName the name of the extension's module. Cannot be {@code null} + * @param stability the stability of the extension + * @param rootRegistration the root management resource registration + * @param extensionRegistryType the type of registry we are working on, which has an effect on things like whether extensions get registered etc. + * + * @return the {@link ExtensionContext}. Will not return {@code null} + */ + public ExtensionContext getExtensionContext(final String moduleName, Stability stability, ManagementResourceRegistration rootRegistration, ExtensionRegistryType extensionRegistryType) { // Can't use processType.isServer() to determine where to look for profile reg because a lot of test infrastructure // doesn't add the profile mrr even in HC-based tests ManagementResourceRegistration profileRegistration = rootRegistration.getSubModel(PathAddress.pathAddress(PathElement.pathElement(PROFILE))); @@ -373,7 +391,7 @@ public ExtensionContext getExtensionContext(final String moduleName, ManagementR // Hack to restrict extra data to specified extension(s) boolean allowSupplement = legallySupplemented.contains(moduleName); ManagedAuditLogger al = allowSupplement ? auditLogger : null; - return new ExtensionContextImpl(moduleName, profileRegistration, deploymentsRegistration, pathManager, extensionRegistryType, al, this.stability); + return new ExtensionContextImpl(moduleName, stability, profileRegistration, deploymentsRegistration, pathManager, extensionRegistryType, al); } public Set getProfileParsingCompletionHandlers() { @@ -638,11 +656,11 @@ private class ExtensionContextImpl implements ExtensionContext, ExtensionContext private final ManagementResourceRegistration profileRegistration; private final ManagementResourceRegistration deploymentsRegistration; private final ExtensionRegistryType extensionRegistryType; - private final Stability stability; + private final Stability stability; // stability of extension - private ExtensionContextImpl(String extensionName, ManagementResourceRegistration profileResourceRegistration, + private ExtensionContextImpl(String extensionName, Stability stability, ManagementResourceRegistration profileResourceRegistration, ManagementResourceRegistration deploymentsResourceRegistration, PathManager pathManager, - ExtensionRegistryType extensionRegistryType, ManagedAuditLogger auditLogger, Stability stability) { + ExtensionRegistryType extensionRegistryType, ManagedAuditLogger auditLogger) { assert pathManager != null || !processType.isServer() : "pathManager is null"; this.pathManager = pathManager; this.extension = getExtensionInfo(extensionName); @@ -678,8 +696,8 @@ public SubsystemRegistration registerSubsystem(String name, ModelVersion version if (deprecated){ ControllerLogger.DEPRECATED_LOGGER.extensionDeprecated(name); } - SubsystemRegistrationImpl result = new SubsystemRegistrationImpl(name, version, - profileRegistration, deploymentsRegistration, extensionRegistryType, extension.extensionModuleName, processType, stability); + SubsystemRegistrationImpl result = new SubsystemRegistrationImpl(name, version, this.stability, + profileRegistration, deploymentsRegistration, extensionRegistryType, extension.extensionModuleName, processType); if (registerTransformers){ transformerRegistry.loadAndRegisterTransformers(name, version, extension.extensionModuleName); } @@ -715,7 +733,7 @@ public ProcessType getProcessType() { @Override public Stability getStability() { - return this.stability; + return this.profileRegistration.getStability(); } @Override @@ -835,17 +853,17 @@ private class SubsystemRegistrationImpl implements SubsystemRegistration { private final String extensionModuleName; private volatile boolean hostCapable; - private SubsystemRegistrationImpl(String name, ModelVersion version, + private SubsystemRegistrationImpl(String name, ModelVersion version, Stability stability, ManagementResourceRegistration profileRegistration, ManagementResourceRegistration deploymentsRegistration, ExtensionRegistryType extensionRegistryType, String extensionModuleName, - ProcessType processType, Stability stability) { + ProcessType processType) { assert profileRegistration != null; this.name = name; this.profileRegistration = profileRegistration; if (deploymentsRegistration == null){ - this.deploymentsRegistration = ManagementResourceRegistration.Factory.forProcessType(processType, stability).createRegistration(new SimpleResourceDefinition(null, NonResolvingResourceDescriptionResolver.INSTANCE)); + this.deploymentsRegistration = ManagementResourceRegistration.Factory.forProcessType(processType, this.profileRegistration.getStability()).createRegistration(ResourceDefinition.builder(ResourceRegistration.of(null, this.profileRegistration.getStability()), NonResolvingResourceDescriptionResolver.INSTANCE).build()); }else { this.deploymentsRegistration = deploymentsRegistration; } @@ -860,6 +878,11 @@ public Stability getStability() { return this.stability; } + @Override + public boolean enables(F feature) { + return this.profileRegistration.enables(feature); + } + @Override public void setHostCapable() { hostCapable = true; @@ -867,15 +890,25 @@ public void setHostCapable() { @Override public ManagementResourceRegistration registerSubsystemModel(ResourceDefinition resourceDefinition) { - assert resourceDefinition != null : "resourceDefinition is null"; checkHostCapable(); - return profileRegistration.registerSubModel(resourceDefinition); + return this.register(this.profileRegistration, resourceDefinition); } @Override public ManagementResourceRegistration registerDeploymentModel(ResourceDefinition resourceDefinition) { - assert resourceDefinition != null : "resourceDefinition is null"; - return deploymentsRegistration.registerSubModel(resourceDefinition); + return this.register(this.deploymentsRegistration, resourceDefinition); + } + + private ManagementResourceRegistration register(ManagementResourceRegistration parent, ResourceDefinition definition) { + Assert.checkNotNullParam("definition", definition); + Stability childStability = definition.getStability(); + // Propagate parent stability-level to child, if necessary + return parent.registerSubModel((childStability != this.stability) && !childStability.enables(this.stability) ? new ProvidedResourceDefinition(definition) { + @Override + public Stability getStability() { + return SubsystemRegistrationImpl.this.stability; + } + } : definition); } @Override diff --git a/controller/src/main/java/org/jboss/as/controller/extension/ExtensionSubsystemResourceDefinition.java b/controller/src/main/java/org/jboss/as/controller/extension/ExtensionSubsystemResourceDefinition.java index dcb796b3ea3..693c6cb5457 100644 --- a/controller/src/main/java/org/jboss/as/controller/extension/ExtensionSubsystemResourceDefinition.java +++ b/controller/src/main/java/org/jboss/as/controller/extension/ExtensionSubsystemResourceDefinition.java @@ -22,6 +22,7 @@ import org.jboss.as.controller.operations.validation.IntRangeValidator; import org.jboss.as.controller.operations.validation.StringLengthValidator; import org.jboss.as.controller.registry.ManagementResourceRegistration; +import org.jboss.as.version.Stability; import org.jboss.dmr.ModelType; /** @@ -54,8 +55,15 @@ public class ExtensionSubsystemResourceDefinition extends SimpleResourceDefiniti .setRuntimeServiceNotRequired() .build(); + private final Stability stability; + ExtensionSubsystemResourceDefinition() { + this(Stability.DEFAULT); + } + + ExtensionSubsystemResourceDefinition(Stability stability) { super(new Parameters(PathElement.pathElement(SUBSYSTEM), ControllerResolver.getResolver(EXTENSION, SUBSYSTEM)).setRuntime()); + this.stability = stability; } @Override @@ -65,4 +73,9 @@ public void registerAttributes(ManagementResourceRegistration resourceRegistrati resourceRegistration.registerReadOnlyAttribute(MICRO_VERSION, null); resourceRegistration.registerReadOnlyAttribute(XML_NAMESPACES, null); } + + @Override + public Stability getStability() { + return this.stability; + } } diff --git a/controller/src/main/java/org/jboss/as/controller/extension/ParallelExtensionAddHandler.java b/controller/src/main/java/org/jboss/as/controller/extension/ParallelExtensionAddHandler.java index 851dbca46d5..2fcc5b0d4c5 100644 --- a/controller/src/main/java/org/jboss/as/controller/extension/ParallelExtensionAddHandler.java +++ b/controller/src/main/java/org/jboss/as/controller/extension/ParallelExtensionAddHandler.java @@ -20,6 +20,7 @@ import org.jboss.as.controller.OperationFailedException; import org.jboss.as.controller.OperationStepHandler; import org.jboss.as.controller.ParsedBootOp; +import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.operations.common.Util; import org.jboss.as.controller.registry.ManagementResourceRegistration; import org.jboss.dmr.ModelNode; @@ -81,7 +82,7 @@ public void execute(OperationContext context, ModelNode operation) throws Operat for (ParsedBootOp op : extensionAdds) { String module = op.address.getLastElement().getValue(); ExtensionAddHandler addHandler = ExtensionAddHandler.class.cast(op.handler); - Future future = executor.submit(new ExtensionInitializeTask(module, addHandler, rootResourceRegistration)); + Future future = executor.submit(new ExtensionInitializeTask(module, addHandler, rootResourceRegistration, op.getAddress())); futures.put(module, future); } @@ -112,19 +113,21 @@ private static class ExtensionInitializeTask implements Callable