diff --git a/controller/src/main/java/org/jboss/as/controller/logging/ControllerLogger.java b/controller/src/main/java/org/jboss/as/controller/logging/ControllerLogger.java index 1e5fcd337b8..49565759173 100644 --- a/controller/src/main/java/org/jboss/as/controller/logging/ControllerLogger.java +++ b/controller/src/main/java/org/jboss/as/controller/logging/ControllerLogger.java @@ -3802,4 +3802,7 @@ OperationFailedRuntimeException capabilityAlreadyRegisteredInContext(String capa @Message(id = 515, value = "The system property '%s' is deprecated and may be removed in a future version, " + "attribute '%s' on resource '%s' should be used instead.") void systemPropertyDeprecated(String systemProperty, String attribute, String address); + + @Message(id = 516, value = "Parameter %s specifies an invalid module name: %s") + OperationFailedException invalidModuleNameParameter(String parameterName, String moduleName); } diff --git a/controller/src/main/java/org/jboss/as/controller/operations/validation/ModuleNameValidator.java b/controller/src/main/java/org/jboss/as/controller/operations/validation/ModuleNameValidator.java new file mode 100644 index 00000000000..456642abc95 --- /dev/null +++ b/controller/src/main/java/org/jboss/as/controller/operations/validation/ModuleNameValidator.java @@ -0,0 +1,39 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.jboss.as.controller.operations.validation; + +import java.util.function.Predicate; +import java.util.regex.Pattern; + +import org.jboss.as.controller.OperationFailedException; +import org.jboss.as.controller.logging.ControllerLogger; +import org.jboss.dmr.ModelNode; +import org.jboss.dmr.ModelType; + +/** + * Validates that a given parameter is a syntactically valid module name within JBoss Modules. + * N.B. This does not validate that the module actually exists, i.e. can be loaded. + */ +public class ModuleNameValidator extends ModelTypeValidator { + public static final ParameterValidator INSTANCE = new ModuleNameValidator(); + // Ensure module name is valid with filesystem module repository, permitting deprecated slot, if present + private static final Predicate MODULE_NAME_TESTER = Pattern.compile("(?:^\\w+|\\w+\\.\\w+|\\w+\\Q\\:\\E\\w+)+(?:\\:(?:\\w+|\\w+\\.\\w+))?$").asMatchPredicate(); + + private ModuleNameValidator() { + super(ModelType.STRING); + } + + @Override + public void validateParameter(String parameterName, ModelNode value) throws OperationFailedException { + super.validateParameter(parameterName, value); + if (value.isDefined()) { + String moduleName = value.asString(); + if (!MODULE_NAME_TESTER.test(moduleName)) { + throw ControllerLogger.MGMT_OP_LOGGER.invalidModuleNameParameter(parameterName, moduleName); + } + } + } +} diff --git a/controller/src/test/java/org/jboss/as/controller/operation/validation/ModuleNameValidatorTestCase.java b/controller/src/test/java/org/jboss/as/controller/operation/validation/ModuleNameValidatorTestCase.java new file mode 100644 index 00000000000..3bdc165c85d --- /dev/null +++ b/controller/src/test/java/org/jboss/as/controller/operation/validation/ModuleNameValidatorTestCase.java @@ -0,0 +1,35 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.jboss.as.controller.operation.validation; + +import org.jboss.as.controller.OperationFailedException; +import org.jboss.as.controller.operations.validation.ModuleNameValidator; +import org.jboss.as.controller.operations.validation.ParameterValidator; +import org.jboss.dmr.ModelNode; +import org.junit.Assert; +import org.junit.Test; + +/** + * Unit test for ModuleNameValidator + */ +public class ModuleNameValidatorTestCase { + + @Test + public void test() throws OperationFailedException { + ParameterValidator validator = ModuleNameValidator.INSTANCE; + + validator.validateParameter("valid", new ModelNode("org.jboss.modules")); + validator.validateParameter("valid", new ModelNode("org.jboss.modules:main")); + validator.validateParameter("valid", new ModelNode("org.jboss.modules:1.9")); + validator.validateParameter("escaped", new ModelNode("org.jboss.modules.foo\\:bar:main")); + + Assert.assertThrows(OperationFailedException.class, () -> validator.validateParameter("invalid", new ModelNode(".foo.bar"))); + Assert.assertThrows(OperationFailedException.class, () -> validator.validateParameter("invalid", new ModelNode("foo..bar"))); + Assert.assertThrows(OperationFailedException.class, () -> validator.validateParameter("invalid", new ModelNode("foo.bar."))); + Assert.assertThrows(OperationFailedException.class, () -> validator.validateParameter("invalid", new ModelNode("foo.bar:"))); + Assert.assertThrows(OperationFailedException.class, () -> validator.validateParameter("invalid", new ModelNode("foo:bar:main"))); + } +}