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-7087] Support resolution of extension expressions during prep… #6275

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
@@ -0,0 +1,88 @@
/*
* Copyright The WildFly Authors
* SPDX-License-Identifier: Apache-2.0
*/

package org.jboss.as.controller;

import static org.wildfly.common.Assert.checkNotNullParam;

import java.util.Optional;

import org.jboss.as.controller.capability.CapabilityServiceSupport;
import org.jboss.as.controller.capability.RuntimeCapability;
import org.jboss.as.controller.capability.registry.CapabilityScope;
import org.jboss.as.controller.capability.registry.ImmutableCapabilityRegistry;
import org.jboss.as.controller.logging.ControllerLogger;
import org.jboss.msc.service.ServiceName;

/**
* Default implementation of {@link CapabilityServiceSupport}.
*/
public final class DefaultCapabilityServiceSupport implements CapabilityServiceSupport {
private final ImmutableCapabilityRegistry registry;

/**
* Creates a new DefaultCapabilityServiceSupport.
* @param registry a capability registry. Cannot be {@code null}.
*/
public DefaultCapabilityServiceSupport(ImmutableCapabilityRegistry registry) {
checkNotNullParam("registry", registry);
this.registry = registry;
}

@Override
public boolean hasCapability(String capabilityName) {
return registry.hasCapability(capabilityName, CapabilityScope.GLOBAL);
}

@Override
public <T> T getCapabilityRuntimeAPI(String capabilityName, Class<T> apiType) throws NoSuchCapabilityException {
try {
return registry.getCapabilityRuntimeAPI(capabilityName, CapabilityScope.GLOBAL, apiType);
} catch (IllegalStateException e) {
throw new NoSuchCapabilityException(capabilityName);
}
}

@Override
public <T> T getCapabilityRuntimeAPI(String capabilityBaseName, String dynamicPart, Class<T> apiType) throws NoSuchCapabilityException {
String fullName = RuntimeCapability.buildDynamicCapabilityName(capabilityBaseName, dynamicPart);
return getCapabilityRuntimeAPI(fullName, apiType);
}

@Override
public <T> Optional<T> getOptionalCapabilityRuntimeAPI(String capabilityName, Class<T> apiType) {
try {
return Optional.of(getCapabilityRuntimeAPI(capabilityName, apiType));
} catch (NoSuchCapabilityException e) {
return Optional.empty();
}
}

@Override
public <T> Optional<T> getOptionalCapabilityRuntimeAPI(String capabilityBaseName, String dynamicPart, Class<T> apiType) {
try {
return Optional.of(getCapabilityRuntimeAPI(capabilityBaseName, dynamicPart, apiType));
} catch (NoSuchCapabilityException e) {
return Optional.empty();
}
}

@Override
public ServiceName getCapabilityServiceName(String capabilityName) {
try {
return registry.getCapabilityServiceName(capabilityName, CapabilityScope.GLOBAL, null);
} catch (IllegalStateException | IllegalArgumentException ignore) {
// ignore
}
ControllerLogger.ROOT_LOGGER.debugf("CapabilityServiceSupport: Parsing ServiceName for %s", capabilityName);
return ServiceNameFactory.parseServiceName(capabilityName);
}

@Override
public ServiceName getCapabilityServiceName(String capabilityBaseName, String... dynamicPart) {
ServiceName name = getCapabilityServiceName(capabilityBaseName);
return (dynamicPart.length > 0) ? name.append(dynamicPart) : name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import java.util.regex.Pattern;

import org.jboss.as.controller.capability.CapabilityServiceSupport;
import org.jboss.as.controller.extension.ExpressionResolverExtension;
import org.jboss.as.controller.extension.ResolverExtensionRegistry;
import org.jboss.as.controller.logging.ControllerLogger;
Expand All @@ -23,9 +24,9 @@ public interface ExpressionResolver {
Pattern EXPRESSION_PATTERN = Pattern.compile(".*\\$\\{.*}.*");

/**
* Resolves any expressions in the passed in ModelNode.
*
* Expressions may represent system properties, vaulted date, or a custom format to be handled by an
* Resolves any expressions in the passed-in ModelNode.
* <p/>
* Expressions may represent system properties, environment variables or a custom format to be handled by an
* {@link ExpressionResolverExtension} registered using the {@link ResolverExtensionRegistry}.
*
* @param node the ModelNode containing expressions.
Expand All @@ -47,13 +48,11 @@ public interface ExpressionResolver {
ModelNode resolveExpressions(ModelNode node) throws OperationFailedException;

/**
* Resolves any expressions in the passed in ModelNode.
*
* Expressions may represent system properties, vaulted date, or a custom format to be handled by an
* Resolves any expressions in the passed-in ModelNode.
* <p/>
* Expressions may represent system properties, environment variables or a custom format to be handled by an
* {@link ExpressionResolverExtension} registered using the {@link ResolverExtensionRegistry}.
*
* For vaulted data the format is ${VAULT::vault_block::attribute_name::sharedKey}
*
* @param node the ModelNode containing expressions.
* @param context the current {@code OperationContext} to provide additional contextual information.
* @return a copy of the node with expressions resolved
Expand All @@ -75,6 +74,41 @@ default ModelNode resolveExpressions(ModelNode node, OperationContext context) t
return resolveExpressions(node);
}

/**
* Resolves any expressions in the passed-in ModelNode.
* <p/>
* Expressions may represent system properties, environment variables or a custom format to be handled by an
* {@link ExpressionResolverExtension} registered using the {@link ResolverExtensionRegistry}.
*
* @param node the ModelNode containing expressions.
* @param capabilitySupport support object for accessing capability-backed APIs.
* @return a copy of the node with expressions resolved
*
* @throws ExpressionResolutionUserException if {@code expression} is a form understood by the resolver but in some
* way is unacceptable. This should only be thrown due to flaws in the
* provided {@code expression} or the configuration of resources used by
* the resolver extension, which are 'user' problems>. It should not
* be used for internal problems in the resolver extension. If a
* if a security manager exists and its
* {@link SecurityManager#checkPermission checkPermission} method doesn't
* allow access to a relevant system property or environment variable,
* an {@code ExpressionResolutionUserException} should be thrown
* @throws ExpressionResolver.ExpressionResolutionServerException if some other internal expression resolution failure occurs.
*/
default ModelNode resolveExpressions(ModelNode node, CapabilityServiceSupport capabilitySupport) {
try {
return resolveExpressions(node);
} catch (OperationFailedException e) {
// This can be thrown because supposedly an ExpressionResolverExtension could throw
// it from ExpressionResolverExtension.initialize(OperationContext). But per the initialize()
// javadoc it should only do that in response to a user problem determined by using the OperationContext.
// But there is no OperationContext passed in a call to resolveExpressions(ModelNode)!
// That method should remove 'throws OperationFailedException', but that would be a breaking API change.
// So this shouldn't happen and if it does something has gone wrong
throw new IllegalStateException(e);
}
}

/**
* An {@code ExpressionResolver} that can only resolve from system properties
* and environment variables. Should not be used for most product resolution use cases as it does
Expand Down
Loading
Loading