Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WFCORE-6347 Add ServiceDescriptor variants of OperationContext.hasOptionalCapability(...) and CapabilityServiceSupport.hasCapability(...) #5818

Merged
merged 3 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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}
Expand Down Expand Up @@ -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 <strong>mandate</strong> the presence
* of the {@code requested} capability, but the capability will use it at runtime if it is present.
* <p>
* 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 <strong>will not</strong> prevent configuration changes that make {@code requested}
* unavailable.
* </p>
*
* @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 <strong>mandate</strong> the presence
* of the {@code requested} capability, but the capability will use it at runtime if it is present.
* <p>
* 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 <strong>will not</strong> prevent configuration changes that make {@code requested}
* unavailable.
* </p>
*
* @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 <strong>mandate</strong> the presence
* of the {@code requested} capability, but the capability will use it at runtime if it is present.
* <p>
* 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 <strong>will not</strong> prevent configuration changes that make {@code requested}
* unavailable.
* </p>
*
* @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 <strong>mandate</strong> the presence
* of the {@code requested} capability, but the capability will use it at runtime if it is present.
* <p>
* 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 <strong>will not</strong> prevent configuration changes that make {@code requested}
* unavailable.
* </p>
*
* @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<String, String[]> 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 <strong>mandate</strong> the presence
* of the {@code requested} capability, but the capability will use it at runtime if it is present.
* <p>
* 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 <strong>will not</strong> prevent configuration changes that make {@code requested}
* unavailable.
* </p>
*
* @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<String, String[]> 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 <strong>mandate</strong> the presence
* of the {@code requested} capability, but the capability will use it at runtime if it is present.
* <p>
* 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 <strong>will not</strong> prevent configuration changes that make {@code requested}
* unavailable.
* </p>
*
* @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<String, String[]> 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 <strong>mandate</strong> the presence
* of the {@code requested} capability, but the capability will use it at runtime if it is present.
* <p>
* 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 <strong>will not</strong> prevent configuration changes that make {@code requested}
* unavailable.
* </p>
*
* @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<String, String[]> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
import org.jboss.msc.service.ServiceRegistry;
import org.jboss.msc.service.ServiceRegistryException;
import org.jboss.msc.service.ServiceTarget;
import org.wildfly.common.Assert;
import org.wildfly.security.auth.server.SecurityIdentity;

/**
Expand Down Expand Up @@ -1564,6 +1565,8 @@ private void recordRequirement(RuntimeRequirementRegistration reg, Step step) {

@Override
public boolean hasOptionalCapability(String required, String dependent, String attribute) {
Assert.checkNotNullParam("required", required);
Assert.checkNotNullParam("dependent", dependent);
return requestOptionalCapability(required, dependent, true, activeStep, attribute);
}

Expand All @@ -1572,12 +1575,6 @@ boolean requestOptionalCapability(String required, String dependent, boolean run
assertCapabilitiesAvailable(currentStage);
ensureLocalCapabilityRegistry();
RuntimeCapabilityRegistry registry = managementModel.getCapabilityRegistry();
if (dependent == null) {
// WFCORE-900 we're currently forgiving of this, but only for runtime-only requirements
assert runtimeOnly;
CapabilityScope context = createCapabilityContext(step.address);
return registry.hasCapability(required, context);
}
RuntimeRequirementRegistration registration = createRequirementRegistration(required, dependent, runtimeOnly, step, attribute);
CapabilityScope context = registration.getDependentContext();
if (registry.hasCapability(required, context)) {
Expand All @@ -1590,6 +1587,8 @@ boolean requestOptionalCapability(String required, String dependent, boolean run

@Override
public void requireOptionalCapability(String required, String dependent, String attribute) throws OperationFailedException {
Assert.checkNotNullParam("required", required);
Assert.checkNotNullParam("dependent", dependent);
requireOptionalCapability(required, dependent, activeStep, attribute);
}

Expand Down
Loading