diff --git a/controller/src/main/java/org/jboss/as/controller/OperationContext.java b/controller/src/main/java/org/jboss/as/controller/OperationContext.java index ce52a017408..6f867f083bb 100644 --- a/controller/src/main/java/org/jboss/as/controller/OperationContext.java +++ b/controller/src/main/java/org/jboss/as/controller/OperationContext.java @@ -712,6 +712,7 @@ default ServiceTarget getServiceTarget() throws UnsupportedOperationException { * manager exists and its {@link SecurityManager#checkPermission checkPermission} method doesn't allow * access to the relevant system property or environment variable */ + @Override ModelNode resolveExpressions(ModelNode node) throws OperationFailedException; /** @@ -837,7 +838,7 @@ default ServiceTarget getServiceTarget() throws UnsupportedOperationException { * * @throws java.lang.IllegalStateException if {@link #getCurrentStage() the current stage} is not {@link Stage#MODEL} */ - void registerCapability(RuntimeCapability capability); + void registerCapability(RuntimeCapability capability); /** * Registers an additional hard requirement a capability has beyond what it was aware of when {@code capability} @@ -885,6 +886,197 @@ default ServiceTarget getServiceTarget() throws UnsupportedOperationException { */ boolean hasOptionalCapability(String requested, String dependent, String attribute); + /** + * Checks whether one of a capability's optional and runtime-only requirements is present. Only for use in cases + * where the {@code dependent} capability's persistent configuration does not mandate the presence + * of the {@code requested} capability, but the capability will use it at runtime if it is present. + *

+ * This method should be used in preference to {@link #registerAdditionalCapabilityRequirement(String, String, String)} + * when the caller's own configuration doesn't impose a hard requirement for the {@code requested} capability, but, + * if it is present it will be used. Once the caller declares an intent to use the capability by invoking this + * method and getting a {@code true} response, thereafter the system is aware that {@code dependent} is actually + * using {@code requested}, but will not prevent configuration changes that make {@code requested} + * unavailable. + *

+ * + * @param requested the base name of the requested capability. Cannot be {@code null} + * @param dependent the runtime capability that requires the other capability. Cannot be {@code null} + * @param attribute the attribute that triggered this requirement, or {@code null} if no single attribute was responsible + * @return {@code true} if the requested capability is present; {@code false} if not. If {@code true}, hereafter + * {@code dependent}'s requirement for {@code requested} will not be treated as optional. + * @throws IllegalStateException if {@link #getCurrentStage() the current stage} is {@link Stage#MODEL}. + * The complete set of capabilities is not known until the end of the model stage. + */ + default boolean hasOptionalCapability(String requested, RuntimeCapability dependent, AttributeDefinition attribute) { + return this.hasOptionalCapability(requested, dependent.isDynamicallyNamed() ? dependent.getDynamicName(this.getCurrentAddress()) : dependent.getName(), (attribute != null) ? attribute.getName() : null); + } + + /** + * Checks whether one of a capability's optional and runtime-only requirements is present. Only for use in cases + * where the {@code dependent} capability's persistent configuration does not mandate the presence + * of the {@code requested} capability, but the capability will use it at runtime if it is present. + *

+ * This method should be used in preference to {@link #registerAdditionalCapabilityRequirement(String, String, String)} + * when the caller's own configuration doesn't impose a hard requirement for the {@code requested} capability, but, + * if it is present it will be used. Once the caller declares an intent to use the capability by invoking this + * method and getting a {@code true} response, thereafter the system is aware that {@code dependent} is actually + * using {@code requested}, but will not prevent configuration changes that make {@code requested} + * unavailable. + *

+ * + * @param requested the base name of the requested capability. Cannot be {@code null} + * @param requestedSegments the dynamic segments of the requested capability. Cannot be {@code null} + * @param dependent the runtime capability that requires the other capability. Cannot be {@code null} + * @param attribute the attribute that triggered this requirement, or {@code null} if no single attribute was responsible + * @return {@code true} if the requested capability is present; {@code false} if not. If {@code true}, hereafter + * {@code dependent}'s requirement for {@code requested} will not be treated as optional. + * @throws IllegalStateException if {@link #getCurrentStage() the current stage} is {@link Stage#MODEL}. + * The complete set of capabilities is not known until the end of the model stage. + */ + default boolean hasOptionalCapability(String requested, String[] requestedSegments, RuntimeCapability dependent, AttributeDefinition attribute) { + return this.hasOptionalCapability(RuntimeCapability.buildDynamicCapabilityName(requested, requestedSegments), dependent, attribute); + } + + /** + * Checks whether one of a capability's optional and runtime-only requirements is present. Only for use in cases + * where the {@code dependent} capability's persistent configuration does not mandate the presence + * of the {@code requested} capability, but the capability will use it at runtime if it is present. + *

+ * This method should be used in preference to {@link #registerAdditionalCapabilityRequirement(String, String, String)} + * when the caller's own configuration doesn't impose a hard requirement for the {@code requested} capability, but, + * if it is present it will be used. Once the caller declares an intent to use the capability by invoking this + * method and getting a {@code true} response, thereafter the system is aware that {@code dependent} is actually + * using {@code requested}, but will not prevent configuration changes that make {@code requested} + * unavailable. + *

+ * + * @param requested the base name of the requested capability. Cannot be {@code null} + * @param requestedSegments the dynamic segments of the requested capability. Cannot be {@code null} + * @param dependent the runtime capability that requires the other capability. Cannot be {@code null} + * @param attribute the attribute that triggered this requirement, or {@code null} if no single attribute was responsible + * @return {@code true} if the requested capability is present; {@code false} if not. If {@code true}, hereafter + * {@code dependent}'s requirement for {@code requested} will not be treated as optional. + * @throws IllegalStateException if {@link #getCurrentStage() the current stage} is {@link Stage#MODEL}. + * The complete set of capabilities is not known until the end of the model stage. + */ + default boolean hasOptionalCapability(NullaryServiceDescriptor requested, RuntimeCapability dependent, AttributeDefinition attribute) { + return this.hasOptionalCapability(requested.getName(), dependent, attribute); + } + + /** + * Checks whether one of a capability's optional and runtime-only requirements is present. Only for use in cases + * where the {@code dependent} capability's persistent configuration does not mandate the presence + * of the {@code requested} capability, but the capability will use it at runtime if it is present. + *

+ * This method should be used in preference to {@link #registerAdditionalCapabilityRequirement(String, String, String)} + * when the caller's own configuration doesn't impose a hard requirement for the {@code requested} capability, but, + * if it is present it will be used. Once the caller declares an intent to use the capability by invoking this + * method and getting a {@code true} response, thereafter the system is aware that {@code dependent} is actually + * using {@code requested}, but will not prevent configuration changes that make {@code requested} + * unavailable. + *

+ * + * @param requested the service descriptor of the requested capability. Cannot be {@code null} + * @param name the dynamic name segment of the requested capability. + * @param dependent the runtime capability that requires the other capability. Cannot be {@code null} + * @param attribute the attribute that triggered this requirement, or {@code null} if no single attribute was responsible + * @return {@code true} if the requested capability is present; {@code false} if not. If {@code true}, hereafter + * {@code dependent}'s requirement for {@code requested} will not be treated as optional. + * @throws IllegalStateException if {@link #getCurrentStage() the current stage} is {@link Stage#MODEL}. + * The complete set of capabilities is not known until the end of the model stage. + */ + default boolean hasOptionalCapability(UnaryServiceDescriptor requested, String name, RuntimeCapability dependent, AttributeDefinition attribute) { + Map.Entry segments = requested.resolve(name); + return this.hasOptionalCapability(segments.getKey(), segments.getValue(), dependent, attribute); + } + + /** + * Checks whether one of a capability's optional and runtime-only requirements is present. Only for use in cases + * where the {@code dependent} capability's persistent configuration does not mandate the presence + * of the {@code requested} capability, but the capability will use it at runtime if it is present. + *

+ * This method should be used in preference to {@link #registerAdditionalCapabilityRequirement(String, String, String)} + * when the caller's own configuration doesn't impose a hard requirement for the {@code requested} capability, but, + * if it is present it will be used. Once the caller declares an intent to use the capability by invoking this + * method and getting a {@code true} response, thereafter the system is aware that {@code dependent} is actually + * using {@code requested}, but will not prevent configuration changes that make {@code requested} + * unavailable. + *

+ * + * @param requested the service descriptor of the requested capability. Cannot be {@code null} + * @param parent the first dynamic name segment of the requested capability. + * @param child the second dynamic name segment of the requested capability. + * @param dependent the runtime capability that requires the other capability. Cannot be {@code null} + * @param attribute the attribute that triggered this requirement, or {@code null} if no single attribute was responsible + * @return {@code true} if the requested capability is present; {@code false} if not. If {@code true}, hereafter + * {@code dependent}'s requirement for {@code requested} will not be treated as optional. + * @throws IllegalStateException if {@link #getCurrentStage() the current stage} is {@link Stage#MODEL}. + * The complete set of capabilities is not known until the end of the model stage. + */ + default boolean hasOptionalCapability(BinaryServiceDescriptor requested, String parent, String child, RuntimeCapability dependent, AttributeDefinition attribute) { + Map.Entry segments = requested.resolve(parent, child); + return this.hasOptionalCapability(segments.getKey(), segments.getValue(), dependent, attribute); + } + + /** + * Checks whether one of a capability's optional and runtime-only requirements is present. Only for use in cases + * where the {@code dependent} capability's persistent configuration does not mandate the presence + * of the {@code requested} capability, but the capability will use it at runtime if it is present. + *

+ * This method should be used in preference to {@link #registerAdditionalCapabilityRequirement(String, String, String)} + * when the caller's own configuration doesn't impose a hard requirement for the {@code requested} capability, but, + * if it is present it will be used. Once the caller declares an intent to use the capability by invoking this + * method and getting a {@code true} response, thereafter the system is aware that {@code dependent} is actually + * using {@code requested}, but will not prevent configuration changes that make {@code requested} + * unavailable. + *

+ * + * @param requested the service descriptor of the requested capability. Cannot be {@code null} + * @param grandparent the first dynamic name segment of the requested capability. + * @param parent the second dynamic name segment of the requested capability. + * @param child the third dynamic name segment of the requested capability. + * @param dependent the runtime capability that requires the other capability. Cannot be {@code null} + * @param attribute the attribute that triggered this requirement, or {@code null} if no single attribute was responsible + * @return {@code true} if the requested capability is present; {@code false} if not. If {@code true}, hereafter + * {@code dependent}'s requirement for {@code requested} will not be treated as optional. + * @throws IllegalStateException if {@link #getCurrentStage() the current stage} is {@link Stage#MODEL}. + * The complete set of capabilities is not known until the end of the model stage. + */ + default boolean hasOptionalCapability(TernaryServiceDescriptor requested, String grandparent, String parent, String child, RuntimeCapability dependent, AttributeDefinition attribute) { + Map.Entry segments = requested.resolve(grandparent, parent, child); + return this.hasOptionalCapability(segments.getKey(), segments.getValue(), dependent, attribute); + } + + /** + * Checks whether one of a capability's optional and runtime-only requirements is present. Only for use in cases + * where the {@code dependent} capability's persistent configuration does not mandate the presence + * of the {@code requested} capability, but the capability will use it at runtime if it is present. + *

+ * This method should be used in preference to {@link #registerAdditionalCapabilityRequirement(String, String, String)} + * when the caller's own configuration doesn't impose a hard requirement for the {@code requested} capability, but, + * if it is present it will be used. Once the caller declares an intent to use the capability by invoking this + * method and getting a {@code true} response, thereafter the system is aware that {@code dependent} is actually + * using {@code requested}, but will not prevent configuration changes that make {@code requested} + * unavailable. + *

+ * + * @param requested the service descriptor of the requested capability. Cannot be {@code null} + * @param greatGrandparent the first dynamic name segment of the requested capability. + * @param grandparent the second dynamic name segment of the requested capability. + * @param parent the third dynamic name segment of the requested capability. + * @param child the fourth dynamic name segment of the requested capability. + * @param dependent the runtime capability that requires the other capability. Cannot be {@code null} + * @param attribute the attribute that triggered this requirement, or {@code null} if no single attribute was responsible + * @return {@code true} if the requested capability is present; {@code false} if not. If {@code true}, hereafter + * {@code dependent}'s requirement for {@code requested} will not be treated as optional. + * @throws IllegalStateException if {@link #getCurrentStage() the current stage} is {@link Stage#MODEL}. + * The complete set of capabilities is not known until the end of the model stage. + */ + default boolean hasOptionalCapability(QuaternaryServiceDescriptor requested, String greatGrandparent, String grandparent, String parent, String child, RuntimeCapability dependent, AttributeDefinition attribute) { + Map.Entry segments = requested.resolve(greatGrandparent, grandparent, parent, child); + return this.hasOptionalCapability(segments.getKey(), segments.getValue(), dependent, attribute); + } + /** * Requests that one of a capability's optional requirements hereafter be treated as required, until the process is * stopped or reloaded. This request will only be granted if the required capability is already present; otherwise diff --git a/controller/src/main/java/org/jboss/as/controller/capability/CapabilityServiceSupport.java b/controller/src/main/java/org/jboss/as/controller/capability/CapabilityServiceSupport.java index 926b0f0a044..22186fea5e3 100644 --- a/controller/src/main/java/org/jboss/as/controller/capability/CapabilityServiceSupport.java +++ b/controller/src/main/java/org/jboss/as/controller/capability/CapabilityServiceSupport.java @@ -40,6 +40,7 @@ public NoSuchCapabilityException(String message) { super(message); } } + /** * Gets whether a runtime capability with the given name is registered. * @@ -48,6 +49,81 @@ public NoSuchCapabilityException(String message) { */ boolean hasCapability(String capabilityName); + /** + * Indicates whether a runtime capability with the given name and segments is registered. + * + * @param capabilityName the name of the capability. Cannot be {@code null} + * @parem segments the dynamic name segments of the capability. Cannot be {@code null} + * @return {@code true} if there is a capability with the given name registered + */ + default boolean hasCapability(String capabilityName, String... segments) { + return this.hasCapability(RuntimeCapability.buildDynamicCapabilityName(capabilityName, segments)); + } + + /** + * Indicates whether or not a runtime capability with the given descriptor is registered. + * + * @param descriptor the service descriptor of the requested capability + * @return {@code true} if there is a capability with the resolved name registered + */ + default boolean hasCapability(NullaryServiceDescriptor descriptor) { + return this.hasCapability(descriptor.getName()); + } + + /** + * Indicates whether or not a runtime capability with the given descriptor and segment is registered. + * + * @param descriptor the service descriptor of the requested capability + * @param name the dynamic name segment of the requested capability. + * @return {@code true} if there is a capability with the resolved name registered + */ + default boolean hasCapability(UnaryServiceDescriptor descriptor, String name) { + Map.Entry segments = descriptor.resolve(name); + return this.hasCapability(segments.getKey(), segments.getValue()); + } + + /** + * Indicates whether or not a runtime capability with the given descriptor and segments is registered. + * + * @param descriptor the service descriptor of the requested capability + * @param parent the first dynamic name segment of the requested capability. + * @param child the second dynamic name segment of the requested capability. + * @return {@code true} if there is a capability with the resolved name registered + */ + default boolean hasCapability(BinaryServiceDescriptor descriptor, String parent, String child) { + Map.Entry segments = descriptor.resolve(parent, child); + return this.hasCapability(segments.getKey(), segments.getValue()); + } + + /** + * Indicates whether or not a runtime capability with the given descriptor and segments is registered. + * + * @param descriptor the service descriptor of the requested capability + * @param grandparent the first dynamic name segment of the requested capability. + * @param parent the second dynamic name segment of the requested capability. + * @param child the third dynamic name segment of the requested capability. + * @return {@code true} if there is a capability with the resolved name registered + */ + default boolean hasCapability(TernaryServiceDescriptor descriptor, String grandparent, String parent, String child) { + Map.Entry segments = descriptor.resolve(grandparent, parent, child); + return this.hasCapability(segments.getKey(), segments.getValue()); + } + + /** + * Indicates whether or not a runtime capability with the given descriptor and segments is registered. + * + * @param descriptor the service descriptor of the requested capability + * @param greatGrandparent the first dynamic name segment of the requested capability. + * @param grandparent the second dynamic name segment of the requested capability. + * @param parent the third dynamic name segment of the requested capability. + * @param child the fourth dynamic name segment of the requested capability. + * @return {@code true} if there is a capability with the resolved name registered + */ + default boolean hasCapability(QuaternaryServiceDescriptor descriptor, String greatGrandparent, String grandparent, String parent, String child) { + Map.Entry segments = descriptor.resolve(greatGrandparent, grandparent, parent, child); + return this.hasCapability(segments.getKey(), segments.getValue()); + } + /** * Gets the runtime API associated with a given capability, if there is one. * @param capabilityName the name of the capability. Cannot be {@code null}