diff --git a/controller/src/main/java/org/jboss/as/controller/descriptions/ModelDescriptionConstants.java b/controller/src/main/java/org/jboss/as/controller/descriptions/ModelDescriptionConstants.java index 77791e4c28e..1555cb85eb3 100644 --- a/controller/src/main/java/org/jboss/as/controller/descriptions/ModelDescriptionConstants.java +++ b/controller/src/main/java/org/jboss/as/controller/descriptions/ModelDescriptionConstants.java @@ -571,6 +571,7 @@ public class ModelDescriptionConstants { public static final String TYPE = "type"; public static final String UDP = "udp"; public static final String UNDEFINE_ATTRIBUTE_OPERATION = "undefine-attribute"; + public static final String UNSTABLE_API_ANNOTATIONS = "unstable-api-annotations"; public static final String UNDEPLOY = "undeploy"; public static final String UNREADABLE_CHILDREN = "unreadable-children"; public static final String UPLOAD_DEPLOYMENT_BYTES = "upload-deployment-bytes"; diff --git a/core-feature-pack/common/pom.xml b/core-feature-pack/common/pom.xml index 321811326e3..e1a7cf374cc 100644 --- a/core-feature-pack/common/pom.xml +++ b/core-feature-pack/common/pom.xml @@ -526,6 +526,11 @@ org.wildfly.security wildfly-elytron-x500-principal + + org.wildfly.unstable.api.annotation + unstable-api-annotation-classpath-indexer + + org.wildfly.core diff --git a/core-feature-pack/common/src/main/resources/modules/system/layers/base/org/wildfly/_internal/unstable-api-annotation-index/main/content/index.txt b/core-feature-pack/common/src/main/resources/modules/system/layers/base/org/wildfly/_internal/unstable-api-annotation-index/main/content/index.txt new file mode 100644 index 00000000000..917e2043049 --- /dev/null +++ b/core-feature-pack/common/src/main/resources/modules/system/layers/base/org/wildfly/_internal/unstable-api-annotation-index/main/content/index.txt @@ -0,0 +1 @@ +# Comment to include file \ No newline at end of file diff --git a/core-feature-pack/common/src/main/resources/modules/system/layers/base/org/wildfly/_internal/unstable-api-annotation-index/main/module.xml b/core-feature-pack/common/src/main/resources/modules/system/layers/base/org/wildfly/_internal/unstable-api-annotation-index/main/module.xml new file mode 100644 index 00000000000..299b9fcde68 --- /dev/null +++ b/core-feature-pack/common/src/main/resources/modules/system/layers/base/org/wildfly/_internal/unstable-api-annotation-index/main/module.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + diff --git a/core-feature-pack/common/src/main/resources/modules/system/layers/base/org/wildfly/extension/core-management/main/module.xml b/core-feature-pack/common/src/main/resources/modules/system/layers/base/org/wildfly/extension/core-management/main/module.xml index 0b1774f32d1..8c993cf72ce 100644 --- a/core-feature-pack/common/src/main/resources/modules/system/layers/base/org/wildfly/extension/core-management/main/module.xml +++ b/core-feature-pack/common/src/main/resources/modules/system/layers/base/org/wildfly/extension/core-management/main/module.xml @@ -17,14 +17,19 @@ + + + + + diff --git a/core-feature-pack/common/src/main/resources/modules/system/layers/base/org/wildfly/unstable/annotation/api/indexer/main/module.xml b/core-feature-pack/common/src/main/resources/modules/system/layers/base/org/wildfly/unstable/annotation/api/indexer/main/module.xml new file mode 100644 index 00000000000..6b5dcff1cf6 --- /dev/null +++ b/core-feature-pack/common/src/main/resources/modules/system/layers/base/org/wildfly/unstable/annotation/api/indexer/main/module.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + diff --git a/core-management/core-management-subsystem/pom.xml b/core-management/core-management-subsystem/pom.xml index f4b1c730dac..1d8b872538c 100644 --- a/core-management/core-management-subsystem/pom.xml +++ b/core-management/core-management-subsystem/pom.xml @@ -80,6 +80,11 @@ true + + org.wildfly.unstable.api.annotation + unstable-api-annotation-classpath-indexer + + org.jboss.logmanager jboss-logmanager diff --git a/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/CoreManagementExtension.java b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/CoreManagementExtension.java index f378dbcef4d..7e851824c3c 100644 --- a/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/CoreManagementExtension.java +++ b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/CoreManagementExtension.java @@ -11,6 +11,7 @@ import org.jboss.as.controller.ExtensionContext; import org.jboss.as.controller.ModelVersion; import org.jboss.as.controller.PathElement; +import org.jboss.as.controller.PersistentResourceXMLDescriptionWriter; import org.jboss.as.controller.SubsystemRegistration; import org.jboss.as.controller.descriptions.ResourceDescriptionResolver; import org.jboss.as.controller.descriptions.StandardResourceDescriptionResolver; @@ -18,17 +19,21 @@ import org.jboss.as.controller.parsing.ExtensionParsingContext; import org.jboss.as.controller.registry.ManagementResourceRegistration; +import java.util.EnumSet; + /** * @author Jeff Mesnil (c) 2016 Red Hat inc. */ public class CoreManagementExtension implements Extension { public static final String SUBSYSTEM_NAME = "core-management"; - static final PathElement SUBSYSTEM_PATH = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME); + public static final PathElement SUBSYSTEM_PATH = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME); static final PathElement PROCESS_STATE_LISTENER_PATH = PathElement.pathElement("process-state-listener"); static final String RESOURCE_NAME = CoreManagementExtension.class.getPackage().getName() + ".LocalDescriptions"; - private static final ModelVersion CURRENT_VERSION = ModelVersion.create(1, 0, 0); + static final ModelVersion VERSION_1_0_0 = ModelVersion.create(1, 0, 0); + + static final ModelVersion CURRENT_VERSION = VERSION_1_0_0; public static ResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) { StringBuilder prefix = new StringBuilder(SUBSYSTEM_NAME); @@ -44,7 +49,7 @@ public static ResourceDescriptionResolver getResourceDescriptionResolver(final S @Override public void initialize(ExtensionContext context) { final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, CURRENT_VERSION); - subsystem.registerXMLElementWriter(CoreManagementSubsystemParser_1_0::new); + subsystem.registerXMLElementWriter(new PersistentResourceXMLDescriptionWriter(CoreManagementSubsystemSchema_1_0.ALL.get(context.getStability()))); //This subsystem should be runnable on a host subsystem.setHostCapable(); ManagementResourceRegistration registration = subsystem.registerSubsystemModel(new CoreManagementRootResourceDefinition()); @@ -53,8 +58,6 @@ public void initialize(ExtensionContext context) { @Override public void initializeParsers(ExtensionParsingContext context) { - // For the current version we don't use a Supplier as we want its description initialized - // TODO if any new xsd versions are added, use a Supplier for the old version - context.setSubsystemXmlMapping(SUBSYSTEM_NAME, CoreManagementSubsystemParser_1_0.NAMESPACE, new CoreManagementSubsystemParser_1_0()); + context.setSubsystemXmlMappings(CoreManagementExtension.SUBSYSTEM_NAME, EnumSet.allOf(CoreManagementSubsystemSchema_1_0.class)); } } diff --git a/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/CoreManagementRootResourceDefinition.java b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/CoreManagementRootResourceDefinition.java index 2a101f83c23..643e09658b2 100644 --- a/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/CoreManagementRootResourceDefinition.java +++ b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/CoreManagementRootResourceDefinition.java @@ -6,15 +6,31 @@ package org.wildfly.extension.core.management; +import org.jboss.as.controller.AbstractBoottimeAddStepHandler; +import org.jboss.as.controller.AttributeDefinition; +import org.jboss.as.controller.OperationContext; +import org.jboss.as.controller.OperationFailedException; +import org.jboss.as.controller.PersistentResourceDefinition; +import org.jboss.as.controller.ReloadRequiredRemoveStepHandler; +import org.jboss.as.controller.registry.Resource; +import org.jboss.as.server.AbstractDeploymentChainStep; +import org.jboss.as.server.DeploymentProcessorTarget; +import org.jboss.dmr.ModelNode; +import org.jboss.msc.service.ServiceBuilder; +import org.wildfly.extension.core.management.UnstableApiAnnotationResourceDefinition.UnstableApiAnnotationLevel; +import org.wildfly.extension.core.management.deployment.ReportUnstableApiAnnotationsProcessor; +import org.wildfly.extension.core.management.deployment.ScanUnstableApiAnnotationsProcessor; + import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.function.Consumer; -import org.jboss.as.controller.AttributeDefinition; -import org.jboss.as.controller.ModelOnlyAddStepHandler; -import org.jboss.as.controller.PersistentResourceDefinition; -import org.jboss.as.controller.ReloadRequiredRemoveStepHandler; +import static org.jboss.as.server.deployment.Phase.PARSE; +import static org.jboss.as.server.deployment.Phase.PARSE_REPORT_EXPERIMENTAL_ANNOTATIONS; +import static org.jboss.as.server.deployment.Phase.PARSE_SCAN_EXPERIMENTAL_ANNOTATIONS; +import static org.wildfly.extension.core.management.CoreManagementExtension.SUBSYSTEM_NAME; /** * {@link org.jboss.as.controller.ResourceDefinition} for the core-management subsystem root resource. @@ -26,7 +42,7 @@ class CoreManagementRootResourceDefinition extends PersistentResourceDefinition CoreManagementRootResourceDefinition() { super(CoreManagementExtension.SUBSYSTEM_PATH, CoreManagementExtension.getResourceDescriptionResolver(), - ModelOnlyAddStepHandler.INSTANCE, + new CoreManagementAddHandler(), ReloadRequiredRemoveStepHandler.INSTANCE); } @@ -38,7 +54,40 @@ public Collection getAttributes() { @Override protected List getChildren() { return Arrays.asList(ConfigurationChangeResourceDefinition.INSTANCE, - new ProcessStateListenerResourceDefinition() + new ProcessStateListenerResourceDefinition(), + UnstableApiAnnotationResourceDefinition.INSTANCE ); } + + private static class CoreManagementAddHandler extends AbstractBoottimeAddStepHandler { + + @Override + protected void performBoottime(OperationContext context, ModelNode operation, Resource resource) throws OperationFailedException { + + if (context.isNormalServer()) { + context.addStep(new AbstractDeploymentChainStep() { + @Override + protected void execute(DeploymentProcessorTarget processorTarget) { + processorTarget.addDeploymentProcessor(SUBSYSTEM_NAME, PARSE, PARSE_SCAN_EXPERIMENTAL_ANNOTATIONS, + new ScanUnstableApiAnnotationsProcessor(context.getRunningMode(), context.getStability(), UnstableApiAnnotationService.LEVEL_SUPPLIER)); + processorTarget.addDeploymentProcessor(SUBSYSTEM_NAME, PARSE, PARSE_REPORT_EXPERIMENTAL_ANNOTATIONS, + new ReportUnstableApiAnnotationsProcessor(UnstableApiAnnotationService.LEVEL_SUPPLIER)); + } + }, OperationContext.Stage.RUNTIME); + } + + Resource unstableApiResource = resource.getChild(UnstableApiAnnotationResourceDefinition.PATH); + UnstableApiAnnotationLevel level = null; + if (unstableApiResource != null) { + ModelNode model = unstableApiResource.getModel(); + String levelValue = UnstableApiAnnotationResourceDefinition.LEVEL.resolveModelAttribute(context, model).asString(); + level = UnstableApiAnnotationLevel.valueOf(levelValue); + } + + ServiceBuilder sb = context.getCapabilityServiceTarget().addService(); + Consumer serviceConsumer = sb.provides(UnstableApiAnnotationService.SERVICE_NAME); + sb.setInstance(new UnstableApiAnnotationService(serviceConsumer, level)); + sb.install(); + } + } } diff --git a/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/CoreManagementSubsystemParser_1_0.java b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/CoreManagementSubsystemParser_1_0.java deleted file mode 100644 index 5754f314900..00000000000 --- a/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/CoreManagementSubsystemParser_1_0.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright The WildFly Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.wildfly.extension.core.management; - -import static org.jboss.as.controller.PersistentResourceXMLDescription.builder; - -import org.jboss.as.controller.PersistentResourceXMLDescription; -import org.jboss.as.controller.PersistentResourceXMLParser; - -/** - * Parser and Marshaller for core-management's {@link #NAMESPACE}. - * - * All resources and attributes must be listed explicitly and not through any collections. - * This ensures that if the resource definitions change in later version (e.g. a new attribute is added), - * this will have no impact on parsing this specific version of the subsystem. - * - * @author Jeff Mesnil (c) 2016 Red Hat inc. - */ -class CoreManagementSubsystemParser_1_0 extends PersistentResourceXMLParser { - - static final String NAMESPACE = "urn:jboss:domain:core-management:1.0"; - - @Override - public PersistentResourceXMLDescription getParserDescription() { - return builder(CoreManagementExtension.SUBSYSTEM_PATH, NAMESPACE) - .addChild(builder(ConfigurationChangeResourceDefinition.PATH).addAttribute(ConfigurationChangeResourceDefinition.MAX_HISTORY)) - .addChild(builder(CoreManagementExtension.PROCESS_STATE_LISTENER_PATH) - .addAttribute(ProcessStateListenerResourceDefinition.LISTENER_CLASS) - .addAttribute(ProcessStateListenerResourceDefinition.LISTENER_MODULE) - .addAttribute(ProcessStateListenerResourceDefinition.PROPERTIES) - .addAttribute(ProcessStateListenerResourceDefinition.TIMEOUT)) - .build(); - } -} diff --git a/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/CoreManagementSubsystemSchema_1_0.java b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/CoreManagementSubsystemSchema_1_0.java new file mode 100644 index 00000000000..aad63bd00ce --- /dev/null +++ b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/CoreManagementSubsystemSchema_1_0.java @@ -0,0 +1,71 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.extension.core.management; + +import org.jboss.as.controller.Feature; +import org.jboss.as.controller.PersistentResourceXMLDescription; +import org.jboss.as.controller.PersistentSubsystemSchema; +import org.jboss.as.controller.SubsystemSchema; +import org.jboss.as.controller.xml.VersionedNamespace; +import org.jboss.as.version.Stability; +import org.jboss.staxmapper.IntVersion; + +import java.util.EnumSet; +import java.util.Map; + +/** + * Parser and Marshaller for core-management subsystem. + * + * All resources and attributes must be listed explicitly and not through any collections. + * This ensures that if the resource definitions change in later version (e.g. a new attribute is added), + * this will have no impact on parsing this specific version of the subsystem. + * + * @author Jeff Mesnil (c) 2016 Red Hat inc. + */ +public enum CoreManagementSubsystemSchema_1_0 implements PersistentSubsystemSchema { + + VERSION_1_0(1), + VERSION_1_0_PREVIEW(1, Stability.PREVIEW); + static final Map ALL = Feature.map(EnumSet.of(VERSION_1_0, VERSION_1_0_PREVIEW)); + + private final VersionedNamespace namespace; + + CoreManagementSubsystemSchema_1_0(int major) { + this.namespace = SubsystemSchema.createLegacySubsystemURN(CoreManagementExtension.SUBSYSTEM_NAME, new IntVersion(major, 0)); + } + + CoreManagementSubsystemSchema_1_0(int major, Stability stability) { + this.namespace = SubsystemSchema.createLegacySubsystemURN(CoreManagementExtension.SUBSYSTEM_NAME, stability, new IntVersion(major, 0)); + } + + @Override + public VersionedNamespace getNamespace() { + return this.namespace; + } + + @Override + public PersistentResourceXMLDescription getXMLDescription() { + PersistentResourceXMLDescription.Factory factory = PersistentResourceXMLDescription.factory(this); + PersistentResourceXMLDescription.Builder builder = factory.builder(CoreManagementExtension.SUBSYSTEM_PATH); + builder.addChild( + factory.builder(ConfigurationChangeResourceDefinition.PATH) + .addAttribute(ConfigurationChangeResourceDefinition.MAX_HISTORY) + .build()); + builder.addChild( + factory.builder(UnstableApiAnnotationResourceDefinition.RESOURCE_REGISTRATION) + .addAttribute(UnstableApiAnnotationResourceDefinition.LEVEL) + .build()); + builder.addChild( + factory.builder(CoreManagementExtension.PROCESS_STATE_LISTENER_PATH) + + .addAttribute(ProcessStateListenerResourceDefinition.LISTENER_CLASS) + .addAttribute(ProcessStateListenerResourceDefinition.LISTENER_MODULE) + .addAttribute(ProcessStateListenerResourceDefinition.PROPERTIES) + .addAttribute(ProcessStateListenerResourceDefinition.TIMEOUT) + .build()); + return builder.build(); + } +} diff --git a/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/UnstableApiAnnotationResourceDefinition.java b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/UnstableApiAnnotationResourceDefinition.java new file mode 100644 index 00000000000..66c359c3e60 --- /dev/null +++ b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/UnstableApiAnnotationResourceDefinition.java @@ -0,0 +1,72 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.wildfly.extension.core.management; + +import org.jboss.as.controller.AttributeDefinition; +import org.jboss.as.controller.PathElement; +import org.jboss.as.controller.PersistentResourceDefinition; +import org.jboss.as.controller.ReloadRequiredAddStepHandler; +import org.jboss.as.controller.ReloadRequiredRemoveStepHandler; +import org.jboss.as.controller.ReloadRequiredWriteAttributeHandler; +import org.jboss.as.controller.ResourceRegistration; +import org.jboss.as.controller.SimpleAttributeDefinition; +import org.jboss.as.controller.SimpleAttributeDefinitionBuilder; +import org.jboss.as.controller.descriptions.ModelDescriptionConstants; +import org.jboss.as.controller.operations.validation.EnumValidator; +import org.jboss.as.controller.registry.ManagementResourceRegistration; +import org.jboss.as.version.Stability; +import org.jboss.dmr.ModelNode; +import org.jboss.dmr.ModelType; + +import java.util.Collection; +import java.util.Collections; + +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SERVICE; +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.UNSTABLE_API_ANNOTATIONS; + +/** + * Resource to list all configuration changes. + * + * @author Emmanuel Hugonnet (c) 2015 Red Hat, inc. + */ +public class UnstableApiAnnotationResourceDefinition extends PersistentResourceDefinition { + + public static final Stability STABILITY = Stability.PREVIEW; + public static final SimpleAttributeDefinition LEVEL = SimpleAttributeDefinitionBuilder.create( + ModelDescriptionConstants.LEVEL, ModelType.STRING, true) + .setValidator(EnumValidator.create(UnstableApiAnnotationLevel.class)) + .setDefaultValue(new ModelNode(UnstableApiAnnotationLevel.LOG.name())) + .build(); + public static final PathElement PATH = PathElement.pathElement(SERVICE, UNSTABLE_API_ANNOTATIONS); + static final ResourceRegistration RESOURCE_REGISTRATION = ResourceRegistration.of(PATH, STABILITY); + static final UnstableApiAnnotationResourceDefinition INSTANCE = new UnstableApiAnnotationResourceDefinition(); + + private UnstableApiAnnotationResourceDefinition() { + super( + new Parameters( + RESOURCE_REGISTRATION, + CoreManagementExtension.getResourceDescriptionResolver(UNSTABLE_API_ANNOTATIONS)) + .setAddHandler(ReloadRequiredAddStepHandler.INSTANCE) + .setRemoveHandler(ReloadRequiredRemoveStepHandler.INSTANCE)); + } + + + @Override + public void registerAttributes(ManagementResourceRegistration resourceRegistration) { + super.registerAttributes(resourceRegistration); + resourceRegistration.registerReadWriteAttribute(LEVEL, null, ReloadRequiredWriteAttributeHandler.INSTANCE); + } + + @Override + public Collection getAttributes() { + return Collections.emptyList(); + } + + public enum UnstableApiAnnotationLevel { + LOG, + ERROR + } + +} diff --git a/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/UnstableApiAnnotationService.java b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/UnstableApiAnnotationService.java new file mode 100644 index 00000000000..3546f12fe6d --- /dev/null +++ b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/UnstableApiAnnotationService.java @@ -0,0 +1,55 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.extension.core.management; + +import org.jboss.msc.Service; +import org.jboss.msc.service.ServiceName; +import org.jboss.msc.service.StartContext; +import org.jboss.msc.service.StartException; +import org.jboss.msc.service.StopContext; +import org.wildfly.extension.core.management.UnstableApiAnnotationResourceDefinition.UnstableApiAnnotationLevel; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class UnstableApiAnnotationService implements Service { + + public static ServiceName SERVICE_NAME = ServiceName.JBOSS.append("core-management", "unstable-api-annotation", "level"); + private final Consumer serviceConsumer; + private final UnstableApiAnnotationLevel level; + static final UnstableApiAnnotationLevelSupplier LEVEL_SUPPLIER = new UnstableApiAnnotationLevelSupplier(); + + public UnstableApiAnnotationService(Consumer serviceConsumer, UnstableApiAnnotationLevel level) { + this.serviceConsumer = serviceConsumer; + this.level = level; + } + + public UnstableApiAnnotationLevel getLevel() { + return level; + } + + @Override + public void start(StartContext context) throws StartException { + serviceConsumer.accept(this); + LEVEL_SUPPLIER.level = level; + } + + @Override + public void stop(StopContext context) { + serviceConsumer.accept(null); + LEVEL_SUPPLIER.level = level; + } + + private static class UnstableApiAnnotationLevelSupplier implements Supplier { + private volatile UnstableApiAnnotationLevel level; + @Override + public UnstableApiAnnotationLevel get() { + return level; + } + } + + +} diff --git a/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/deployment/ReportUnstableApiAnnotationsProcessor.java b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/deployment/ReportUnstableApiAnnotationsProcessor.java new file mode 100644 index 00000000000..77be273fc16 --- /dev/null +++ b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/deployment/ReportUnstableApiAnnotationsProcessor.java @@ -0,0 +1,333 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.extension.core.management.deployment; + +import org.jboss.as.server.deployment.Attachments; +import org.jboss.as.server.deployment.DeploymentPhaseContext; +import org.jboss.as.server.deployment.DeploymentUnit; +import org.jboss.as.server.deployment.DeploymentUnitProcessingException; +import org.jboss.as.server.deployment.DeploymentUnitProcessor; +import org.jboss.as.server.deployment.annotation.CompositeIndex; +import org.jboss.jandex.DotName; +import org.jboss.logging.Logger; +import org.wildfly.extension.core.management.UnstableApiAnnotationResourceDefinition.UnstableApiAnnotationLevel; +import org.wildfly.unstable.api.annotation.classpath.runtime.bytecode.AnnotatedAnnotationUsage; +import org.wildfly.unstable.api.annotation.classpath.runtime.bytecode.AnnotatedClassUsage; +import org.wildfly.unstable.api.annotation.classpath.runtime.bytecode.AnnotatedFieldReference; +import org.wildfly.unstable.api.annotation.classpath.runtime.bytecode.AnnotatedMethodReference; +import org.wildfly.unstable.api.annotation.classpath.runtime.bytecode.AnnotationUsage; +import org.wildfly.unstable.api.annotation.classpath.runtime.bytecode.ClassInfoScanner; +import org.wildfly.unstable.api.annotation.classpath.runtime.bytecode.ExtendsAnnotatedClass; +import org.wildfly.unstable.api.annotation.classpath.runtime.bytecode.ImplementsAnnotatedInterface; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Set; +import java.util.function.Supplier; + +import static org.wildfly.extension.core.management.logging.CoreManagementLogger.UNSUPPORTED_ANNOTATION_LOGGER; + +public class ReportUnstableApiAnnotationsProcessor implements DeploymentUnitProcessor { + + private final Supplier levelSupplier; + + public ReportUnstableApiAnnotationsProcessor(Supplier levelSupplier) { + this.levelSupplier = levelSupplier; + } + + /** + * Process this deployment for annotations. This will use an annotation indexer to create an index of all annotations + * found in this deployment and attach it to the deployment unit context. + * + * @param phaseContext the deployment unit context + * @throws DeploymentUnitProcessingException + * + */ + public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException { + final DeploymentUnit du = phaseContext.getDeploymentUnit(); + DeploymentUnit top = du.getParent() == null ? du : du.getParent(); + ClassInfoScanner scanner = top.getAttachment(UnstableApiAnnotationAttachments.UNSTABLE_API_ANNOTATION_SCANNER); + if (scanner == null) { + return; + } + + // ScanExperimentalAnnotationsProcessor has looked for class, interface, method and field usage where those + // parts have been annotated with an annotation flagged as experimental. + // The finale part is to check the annotations indexed by Jandex + CompositeIndex index = du.getAttachment(Attachments.COMPOSITE_ANNOTATION_INDEX); + scanner.checkAnnotationIndex(annotationName -> index.getAnnotations(DotName.createSimple(annotationName))); + + Set usages = scanner.getUsages(); + + if (!usages.isEmpty()) { + AnnotationUsages annotationUsages = AnnotationUsages.parseAndGroup(scanner.getUsages()); + AnnotationUsageReporter reporter = getAnnotationUsageReporter(phaseContext, top); + if (reporter.isEnabled()) { + reportAnnotationUsages(top, annotationUsages, reporter); + } + } + } + + private void reportAnnotationUsages(DeploymentUnit top, AnnotationUsages annotationUsages, AnnotationUsageReporter reporter) throws DeploymentUnitProcessingException { + reporter.header(UNSUPPORTED_ANNOTATION_LOGGER.deploymentContainsUnstableApiAnnotations(top.getName())); + for (ExtendsAnnotatedClass ext : annotationUsages.extendsAnnotatedClasses) { + reporter.reportAnnotationUsage( + UNSUPPORTED_ANNOTATION_LOGGER.classExtendsClassWithUnstableApiAnnotations( + ext.getSourceClass(), + ext.getSuperClass(), + ext.getAnnotations())); + } + for (ImplementsAnnotatedInterface imp : annotationUsages.implementsAnnotatedInterfaces) { + reporter.reportAnnotationUsage( + UNSUPPORTED_ANNOTATION_LOGGER.classImplementsInterfaceWithUnstableApiAnnotations( + imp.getSourceClass(), + imp.getInterface(), + imp.getAnnotations())); + } + for (AnnotatedFieldReference ref : annotationUsages.annotatedFieldReferences) { + reporter.reportAnnotationUsage( + UNSUPPORTED_ANNOTATION_LOGGER.classReferencesFieldWithUnstableApiAnnotations( + ref.getSourceClass(), + ref.getFieldClass(), + ref.getFieldName(), + ref.getAnnotations())); + } + for (AnnotatedMethodReference ref : annotationUsages.annotatedMethodReferences) { + reporter.reportAnnotationUsage( + UNSUPPORTED_ANNOTATION_LOGGER.classReferencesMethodWithUnstableApiAnnotations( + ref.getSourceClass(), + ref.getMethodClass(), + ref.getMethodName(), + ref.getDescriptor(), + ref.getAnnotations())); + } + for (AnnotatedClassUsage ref : annotationUsages.annotatedClassUsages) { + reporter.reportAnnotationUsage( + UNSUPPORTED_ANNOTATION_LOGGER.classReferencesClassWithUnstableApiAnnotations( + ref.getSourceClass(), + ref.getReferencedClass(), + ref.getAnnotations())); + } + for (AnnotatedAnnotationUsage ref : annotationUsages.annotatedAnnotationUsages) { + reporter.reportAnnotationUsage( + UNSUPPORTED_ANNOTATION_LOGGER.classUsesAnnotatedAnnotations( + ref.getClazz(), ref.getAnnotations())); + } + + reporter.complete(); + } + + private AnnotationUsageReporter getAnnotationUsageReporter(DeploymentPhaseContext ctx, DeploymentUnit top) throws DeploymentUnitProcessingException { + UnstableApiAnnotationLevel level = levelSupplier.get(); + if (level == UnstableApiAnnotationLevel.ERROR) { + return new ErrorAnnotationUsageReporter(); + } + return new WarningAnnotationUsageReporter(); + } + + + private static class AnnotationUsages { + + + private final List extendsAnnotatedClasses; + private final List implementsAnnotatedInterfaces; + private final List annotatedFieldReferences; + private final List annotatedMethodReferences; + private final List annotatedClassUsages; + private final List annotatedAnnotationUsages; + public AnnotationUsages(List extendsAnnotatedClasses, + List implementsAnnotatedInterfaces, + List annotatedFieldReferences, + List annotatedMethodReferences, + List annotatedClassUsages, + List annotatedAnnotationUsages) { + + this.extendsAnnotatedClasses = extendsAnnotatedClasses; + this.implementsAnnotatedInterfaces = implementsAnnotatedInterfaces; + this.annotatedFieldReferences = annotatedFieldReferences; + this.annotatedMethodReferences = annotatedMethodReferences; + this.annotatedClassUsages = annotatedClassUsages; + this.annotatedAnnotationUsages = annotatedAnnotationUsages; + } + + static AnnotationUsages parseAndGroup(Set usages) { + List extendsAnnotatedClasses = new ArrayList<>(); + List implementsAnnotatedInterfaces = new ArrayList<>(); + List annotatedFieldReferences = new ArrayList<>(); + List annotatedMethodReferences = new ArrayList<>(); + List annotatedClassUsages = new ArrayList<>(); + List annotatedAnnotationUsages = new ArrayList<>(); + for (AnnotationUsage usage : usages) { + switch (usage.getType()) { + case EXTENDS_CLASS: { + ExtendsAnnotatedClass ext = usage.asExtendsAnnotatedClass(); + extendsAnnotatedClasses.add(ext); + } + break; + case IMPLEMENTS_INTERFACE: { + ImplementsAnnotatedInterface imp = usage.asImplementsAnnotatedInterface(); + implementsAnnotatedInterfaces.add(imp); + } + break; + case FIELD_REFERENCE: { + AnnotatedFieldReference ref = usage.asAnnotatedFieldReference(); + annotatedFieldReferences.add(ref); + } + break; + case METHOD_REFERENCE: { + AnnotatedMethodReference ref = usage.asAnnotatedMethodReference(); + annotatedMethodReferences.add(ref); + } + break; + case CLASS_USAGE: { + AnnotatedClassUsage ref = usage.asAnnotatedClassUsage(); + annotatedClassUsages.add(ref); + } + break; + case ANNOTATED_ANNOTATION_USAGE: { + AnnotatedAnnotationUsage ref = usage.asAnnotatedAnnotationUsage(); + annotatedAnnotationUsages.add(ref); + } + break; + } + } + extendsAnnotatedClasses.sort(new Comparator<>() { + @Override + public int compare(ExtendsAnnotatedClass o1, ExtendsAnnotatedClass o2) { + int i = o1.getSourceClass().compareTo(o2.getSourceClass()); + if (i == 0) { + i = o1.getSuperClass().compareTo(o2.getSuperClass()); + } + + return i; + } + }); + implementsAnnotatedInterfaces.sort(new Comparator<>() { + @Override + public int compare(ImplementsAnnotatedInterface o1, ImplementsAnnotatedInterface o2) { + int i = o1.getSourceClass().compareTo(o2.getSourceClass()); + if (i == 0) { + i = o1.getInterface().compareTo(o2.getInterface()); + } + + return i; + } + }); + annotatedFieldReferences.sort(new Comparator<>() { + @Override + public int compare(AnnotatedFieldReference o1, AnnotatedFieldReference o2) { + int i = o1.getSourceClass().compareTo(o2.getSourceClass()); + if (i == 0) { + i = o1.getFieldClass().compareTo(o2.getFieldClass()); + if (i == 0) { + i = o1.getFieldName().compareTo(o2.getFieldName()); + } + } + return i; + } + }); + annotatedMethodReferences.sort(new Comparator<>() { + @Override + public int compare(AnnotatedMethodReference o1, AnnotatedMethodReference o2) { + int i = o1.getSourceClass().compareTo(o2.getSourceClass()); + if (i == 0) { + i = o1.getMethodClass().compareTo(o2.getMethodClass()); + if (i == 0) { + i = o1.getMethodName().compareTo(o2.getMethodName()); + if (i == 0) { + i = o1.getDescriptor().compareTo(o2.getDescriptor()); + } + } + } + return i; + } + }); + annotatedClassUsages.sort(new Comparator<>() { + @Override + public int compare(AnnotatedClassUsage o1, AnnotatedClassUsage o2) { + int i = o1.getSourceClass().compareTo(o2.getSourceClass()); + if (i == 0) { + i = o1.getReferencedClass().compareTo(o2.getReferencedClass()); + } + return i; + } + }); + annotatedAnnotationUsages.sort(new Comparator<>(){ + @Override + public int compare(AnnotatedAnnotationUsage o1, AnnotatedAnnotationUsage o2) { + return o1.getClazz().compareTo(o2.getClazz()); + } + }); + + return new AnnotationUsages(extendsAnnotatedClasses, + implementsAnnotatedInterfaces, + annotatedFieldReferences, + annotatedMethodReferences, + annotatedClassUsages, + annotatedAnnotationUsages); + } + } + + + + private interface AnnotationUsageReporter { + void header(String message); + + void reportAnnotationUsage(String message); + + void complete() throws DeploymentUnitProcessingException; + + boolean isEnabled(); + } + + private class WarningAnnotationUsageReporter implements AnnotationUsageReporter { + @Override + public void header(String message) { + UNSUPPORTED_ANNOTATION_LOGGER.warn(message); + } + + @Override + public void reportAnnotationUsage(String message) { + UNSUPPORTED_ANNOTATION_LOGGER.warn(message); + } + + @Override + public void complete() throws DeploymentUnitProcessingException { + + } + + @Override + public boolean isEnabled() { + return UNSUPPORTED_ANNOTATION_LOGGER.isEnabled(Logger.Level.WARN); + } + } + + private class ErrorAnnotationUsageReporter implements AnnotationUsageReporter { + private final StringBuilder sb = new StringBuilder(); + @Override + public void header(String message) { + sb.append(message); + } + + @Override + public void reportAnnotationUsage(String message) { + sb.append("\n"); + sb.append("-"); + sb.append(message); + } + + @Override + public void complete() throws DeploymentUnitProcessingException { + throw new DeploymentUnitProcessingException(sb.toString()); + } + + @Override + public boolean isEnabled() { + return true; + } + } +} \ No newline at end of file diff --git a/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/deployment/ScanUnstableApiAnnotationsProcessor.java b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/deployment/ScanUnstableApiAnnotationsProcessor.java new file mode 100644 index 00000000000..a8fe09622a6 --- /dev/null +++ b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/deployment/ScanUnstableApiAnnotationsProcessor.java @@ -0,0 +1,179 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.extension.core.management.deployment; + +import org.jboss.as.controller.RunningMode; +import org.jboss.as.server.deployment.Attachments; +import org.jboss.as.server.deployment.DeploymentPhaseContext; +import org.jboss.as.server.deployment.DeploymentUnit; +import org.jboss.as.server.deployment.DeploymentUnitProcessingException; +import org.jboss.as.server.deployment.DeploymentUnitProcessor; +import org.jboss.as.server.deployment.DeploymentUtils; +import org.jboss.as.server.deployment.module.ResourceRoot; +import org.jboss.as.server.logging.ServerLogger; +import org.jboss.as.version.Stability; +import org.jboss.modules.Module; +import org.jboss.modules.ModuleClassLoader; +import org.jboss.modules.ModuleLoadException; +import org.jboss.modules.ModuleLoader; +import org.jboss.vfs.VirtualFile; +import org.jboss.vfs.VisitorAttributes; +import org.jboss.vfs.util.SuffixMatchFilter; +import org.wildfly.extension.core.management.UnstableApiAnnotationResourceDefinition; +import org.wildfly.extension.core.management.logging.CoreManagementLogger; +import org.wildfly.unstable.api.annotation.classpath.index.RuntimeIndex; +import org.wildfly.unstable.api.annotation.classpath.runtime.bytecode.ClassInfoScanner; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +public class ScanUnstableApiAnnotationsProcessor implements DeploymentUnitProcessor { + + private final RuntimeIndex runtimeIndex; + + // If set we will output some extra information to the logs during testing, so we can verify the number of classes scanned + // This is important for WildFly to make sure that the scanning of nested archives (especially wars and ears) is + // working as expected and to guard against scanning classes multiple times (which happened during the development of this feature) + private final String EXTRA_TEST_OUTPUT_PROPERTY = "org.wildfly.test.unstable-api-annotation.extra-output"; + + private static final String BASE_MODULE_NAME = "org.wildfly._internal.unstable-api-annotation-index"; + private static final String INDEX_FILE = "index.txt"; + private final Stability stability; + private final Supplier levelSupplier; + + private boolean extraTestOutput; + + public ScanUnstableApiAnnotationsProcessor(RunningMode runningMode, Stability stability, Supplier levelSupplier) { + this.stability = stability; + this.levelSupplier = levelSupplier; + extraTestOutput = System.getProperties().containsKey(EXTRA_TEST_OUTPUT_PROPERTY); + + boolean enableScanning = true; + if (runningMode == RunningMode.ADMIN_ONLY) { + enableScanning = false; + } else if (stability.enables(Stability.EXPERIMENTAL) || !stability.enables(UnstableApiAnnotationResourceDefinition.STABILITY)) { + // We don't care about scanning at the experimental level. + // Also, we need to be at the level where the feature is enabled or lower + enableScanning = false; + } + + RuntimeIndex runtimeIndex = null; + if (enableScanning) { + ModuleLoader moduleLoader = ((ModuleClassLoader) this.getClass().getClassLoader()).getModule().getModuleLoader(); + Module module = null; + try { + module = moduleLoader.loadModule(BASE_MODULE_NAME); + } catch (ModuleLoadException e) { + // TODO make this module part of core so it is always there + } + if (module != null) { + URL url = module.getExportedResource(INDEX_FILE); + List urls = new ArrayList<>(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) { + String fileName = reader.readLine(); + while (fileName != null) { + fileName = fileName.trim(); + if (!fileName.isEmpty() && !fileName.startsWith("#")) { + urls.add(module.getExportedResource(fileName)); + } + fileName = reader.readLine(); + } + + if (!urls.isEmpty()) { + runtimeIndex = RuntimeIndex.load(urls); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + this.runtimeIndex = runtimeIndex; + } + + /** + * Process this deployment for annotations. This will use an annotation indexer to create an index of all annotations + * found in this deployment and attach it to the deployment unit context. + * + * @param phaseContext the deployment unit context + * @throws DeploymentUnitProcessingException + */ + public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException { + if (runtimeIndex == null) { + return; + } + if (levelSupplier.get() == null) { + return; + } + final DeploymentUnit du = phaseContext.getDeploymentUnit(); + DeploymentUnit top = DeploymentUtils.getTopDeploymentUnit(du); + + ClassInfoScanner scanner = top.getAttachment(UnstableApiAnnotationAttachments.UNSTABLE_API_ANNOTATION_SCANNER); + if (scanner == null) { + scanner = new ClassInfoScanner(runtimeIndex); + top.putAttachment(UnstableApiAnnotationAttachments.UNSTABLE_API_ANNOTATION_SCANNER, scanner); + } + ProcessedClassCounter counter = new ProcessedClassCounter(); + + ServerLogger.DEPLOYMENT_LOGGER.debug("Scanning deployment for unstable api annotations"); + List resourceRoots = DeploymentUtils.allResourceRoots(du); + for (ResourceRoot root : resourceRoots) { + + // The EarStructureProcessor and WarStructureProcessor in full will set this accordingly + Boolean shouldIndexResource = root.getAttachment(Attachments.INDEX_RESOURCE_ROOT); + if (shouldIndexResource != null && !shouldIndexResource) { + continue; + } + + if (root.getAttachment(UnstableApiAnnotationAttachments.UNSTABLE_API_ANNOTATIONS_SCANNED) != null) { + continue; + } + final VisitorAttributes visitorAttributes = new VisitorAttributes(); + visitorAttributes.setLeavesOnly(true); + visitorAttributes.setRecurseFilter(f-> true); + + try { + final List classChildren = root.getRoot().getChildren(new SuffixMatchFilter(".class", visitorAttributes)); + for (VirtualFile file : classChildren) { + if (file.isFile() && file.getName().endsWith(".class")) { + try (InputStream in = file.openStream()) { + scanner.scanClass(in); + counter.incrementClassesScannedCount(); + } + } + } + } catch (IOException e) { + throw new RuntimeException(e); + } + root.putAttachment(UnstableApiAnnotationAttachments.UNSTABLE_API_ANNOTATIONS_SCANNED, true); + } + + long time = (System.currentTimeMillis() - counter.startTime); + CoreManagementLogger.UNSUPPORTED_ANNOTATION_LOGGER.debugf("Unstable annotation api scan took %d ms to scan %d classes", time, counter.getClassesScannedCount()); + if (extraTestOutput) { + CoreManagementLogger.UNSUPPORTED_ANNOTATION_LOGGER.testOutputNumberOfClassesScanned(counter.getClassesScannedCount()); + } + } + + public static class ProcessedClassCounter { + private final long startTime = System.currentTimeMillis(); + + private volatile int classesScannedCount = 0; + + void incrementClassesScannedCount() { + classesScannedCount++; + } + + public int getClassesScannedCount() { + return classesScannedCount; + } + } +} diff --git a/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/deployment/UnstableApiAnnotationAttachments.java b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/deployment/UnstableApiAnnotationAttachments.java new file mode 100644 index 00000000000..e3218dc28ba --- /dev/null +++ b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/deployment/UnstableApiAnnotationAttachments.java @@ -0,0 +1,16 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.extension.core.management.deployment; + +import org.jboss.as.server.deployment.AttachmentKey; +import org.wildfly.unstable.api.annotation.classpath.runtime.bytecode.ClassInfoScanner; + +class UnstableApiAnnotationAttachments { + public static final AttachmentKey UNSTABLE_API_ANNOTATION_SCANNER = AttachmentKey.create(ClassInfoScanner.class); + + public static final AttachmentKey UNSTABLE_API_ANNOTATIONS_SCANNED = AttachmentKey.create(Boolean.class); + +} diff --git a/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/logging/CoreManagementLogger.java b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/logging/CoreManagementLogger.java index 7926bc676d3..63860b511f0 100644 --- a/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/logging/CoreManagementLogger.java +++ b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/logging/CoreManagementLogger.java @@ -6,6 +6,7 @@ package org.wildfly.extension.core.management.logging; import static org.jboss.logging.Logger.Level.ERROR; +import static org.jboss.logging.Logger.Level.INFO; import org.jboss.as.controller.OperationFailedException; import org.jboss.logging.BasicLogger; @@ -15,6 +16,8 @@ import org.jboss.logging.annotations.Message; import org.jboss.logging.annotations.MessageLogger; +import java.util.Set; + /** * * @author Emmanuel Hugonnet (c) 2016 Red Hat, inc. @@ -27,6 +30,8 @@ public interface CoreManagementLogger extends BasicLogger { */ CoreManagementLogger ROOT_LOGGER = Logger.getMessageLogger(CoreManagementLogger.class, "org.wildfly.extension.core.management"); + CoreManagementLogger UNSUPPORTED_ANNOTATION_LOGGER = Logger.getMessageLogger(CoreManagementLogger.class, "org.wildfly.annotation.unsupported"); + // @Message(id = 1, value = "The resource %s wasn't working properly and has been removed.") // String removedOutOfOrderResource(final String address); @@ -53,4 +58,31 @@ public interface CoreManagementLogger extends BasicLogger { @Message(id = 8, value = "Error to instantiate instance of class %s from module %s") OperationFailedException errorToInstantiateClassInstanceFromModule(String className, String moduleID); + + @Message(id = 9, value = "%s contains usage of annotations which indicate unstable API.") + String deploymentContainsUnstableApiAnnotations(String deployment); + + @Message(id = 10, value = "%s extends %s which has been annotated with %s") + String classExtendsClassWithUnstableApiAnnotations(String sourceClass, String superClass, Set annotations); + + @Message(id = 11, value = "%s implements %s which has been annotated with %s") + String classImplementsInterfaceWithUnstableApiAnnotations(String sourceClass, String superClass, Set annotations); + + @Message(id = 12, value = "%s references field %s.%s which has been annotated with %s") + String classReferencesFieldWithUnstableApiAnnotations(String sourceClass, String fieldClass, String fieldName, Set annotations); + + @Message(id = 13, value = "%s references method %s.%s%s which has been annotated with %s") + String classReferencesMethodWithUnstableApiAnnotations(String sourceClass, String methodClass, String methodName, String methodSignature, Set annotations); + + @Message(id = 14, value = "%s references class %s which has been annotated with %s") + String classReferencesClassWithUnstableApiAnnotations(String sourceClass, String referencedClass, Set annotations); + + @Message(id = 15, value = "Class %s is annotated with one or more annotations which in turn have been annotated with annotations indicating unstable api: %s") + String classUsesAnnotatedAnnotations(String clazz, Set annotations); + + // For testing only + @LogMessage(level = INFO) + @Message(id = 16, value = "%d") + void testOutputNumberOfClassesScanned(int number); + } diff --git a/core-management/core-management-subsystem/src/main/resources/org/wildfly/extension/core/management/LocalDescriptions.properties b/core-management/core-management-subsystem/src/main/resources/org/wildfly/extension/core/management/LocalDescriptions.properties index fa9f915c3a7..5ed40797c43 100644 --- a/core-management/core-management-subsystem/src/main/resources/org/wildfly/extension/core/management/LocalDescriptions.properties +++ b/core-management/core-management-subsystem/src/main/resources/org/wildfly/extension/core/management/LocalDescriptions.properties @@ -16,6 +16,11 @@ core-management.configuration-changes.remove=Remove the configuration changes an core-management.configuration-changes.max-history=The maximum number of configuration changes stored in history. core-management.configuration-changes.list-changes=List the last configuration changes. +core-management.unstable-api-annotations=Service to configure how we deal with finding annotations indicating unstable API in user code. +core-management.unstable-api-annotations.add=Add the history for configuration changes. +core-management.unstable-api-annotations.remove=Remove the configuration changes and clear the history. +core-management.unstable-api-annotations.level=Whether to throw an error or log a warning if annotations indicating unstable API. + core-management.process-state-listener=Process state listener. core-management.process-state-listener.add=Add the process-state-listener service. core-management.process-state-listener.add-index=Add the process-state-listener serviceat the specified index. diff --git a/core-management/core-management-subsystem/src/main/resources/schema/wildfly-core-management_preview_1_0.xsd b/core-management/core-management-subsystem/src/main/resources/schema/wildfly-core-management_preview_1_0.xsd new file mode 100644 index 00000000000..3ebcafe0048 --- /dev/null +++ b/core-management/core-management-subsystem/src/main/resources/schema/wildfly-core-management_preview_1_0.xsd @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + Configuration for the history of configuration changes. + + + + + + + Number of configuration changes that are available in history. + + + + + + + + + Configuration of the handling of finding unstable api annotations in the + user's code + + + + + + + Whether to log or throw an error if use of unstable api annotations are found + + + + + + + + + + + + + + + + Configuration for a process state listener. + + + + + + + + Configuration properties for the process state listener. + + + + + + + + Name of the process state listener. + + + + + + + ControlledProcessStateListener class implementation. + + + + + + + Module where the ControlledProcessStateListener implementation class may be found. + + + + + + + Timeout used in seconds, for listener operations. + If an individual listener operation takes longer than this timeout it will be canceled. + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core-management/core-management-subsystem/src/test/java/org/wildfly/extension/core/management/CoreManagementSubsystemTestCase.java b/core-management/core-management-subsystem/src/test/java/org/wildfly/extension/core/management/CoreManagementSubsystemTestCase.java deleted file mode 100644 index f002ce0ed61..00000000000 --- a/core-management/core-management-subsystem/src/test/java/org/wildfly/extension/core/management/CoreManagementSubsystemTestCase.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright The WildFly Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.wildfly.extension.core.management; - -import java.io.IOException; - -import org.jboss.as.controller.ProcessType; -import org.jboss.as.controller.RunningMode; -import org.jboss.as.subsystem.test.AbstractSubsystemBaseTest; -import org.jboss.as.subsystem.test.AdditionalInitialization; - -/** - * @author Jeff Mesnil (c) 2016 Red Hat Inc. - */ -public class CoreManagementSubsystemTestCase extends AbstractSubsystemBaseTest { - - public CoreManagementSubsystemTestCase() { - super(CoreManagementExtension.SUBSYSTEM_NAME, new CoreManagementExtension()); - } - - @Override - protected String getSubsystemXml() throws IOException { - return readResource("core-management-subsystem-1_0.xml"); - } - - @Override - protected AdditionalInitialization createAdditionalInitialization() { - return new AdditionalInitialization() { - - @Override - protected ProcessType getProcessType() { - return ProcessType.HOST_CONTROLLER; - } - - @Override - protected RunningMode getRunningMode() { - return RunningMode.ADMIN_ONLY; - } - }; - } -} diff --git a/core-management/core-management-subsystem/src/test/java/org/wildfly/extension/core/management/CoreManagementSubsystem_1_0_TestCase.java b/core-management/core-management-subsystem/src/test/java/org/wildfly/extension/core/management/CoreManagementSubsystem_1_0_TestCase.java new file mode 100644 index 00000000000..7392d29e230 --- /dev/null +++ b/core-management/core-management-subsystem/src/test/java/org/wildfly/extension/core/management/CoreManagementSubsystem_1_0_TestCase.java @@ -0,0 +1,35 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.extension.core.management; + +import org.jboss.as.subsystem.test.AbstractSubsystemSchemaTest; +import org.jboss.as.subsystem.test.AdditionalInitialization; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.EnumSet; + +/** + * @author Jeff Mesnil (c) 2016 Red Hat Inc. + */ +@RunWith(Parameterized.class) +public class CoreManagementSubsystem_1_0_TestCase extends AbstractSubsystemSchemaTest { + + @Parameterized.Parameters(name = "{0}") + public static Iterable getParameters() { + return EnumSet.allOf(CoreManagementSubsystemSchema_1_0.class); + } + + public CoreManagementSubsystem_1_0_TestCase(CoreManagementSubsystemSchema_1_0 schema) { + super(CoreManagementExtension.SUBSYSTEM_NAME, new CoreManagementExtension(), schema, CoreManagementSubsystemSchema_1_0.ALL.get(schema.getStability())); + } + + @Override + protected AdditionalInitialization createAdditionalInitialization() { + return new AdditionalInitialization.AdminOnlyHostControllerAdditionalInitialization(getSubsystemSchema()); + } + +} diff --git a/core-management/core-management-subsystem/src/test/resources/org/wildfly/extension/core/management/core-management-subsystem-1_0.xml b/core-management/core-management-subsystem/src/test/resources/org/wildfly/extension/core/management/core-management-1.0.xml similarity index 53% rename from core-management/core-management-subsystem/src/test/resources/org/wildfly/extension/core/management/core-management-subsystem-1_0.xml rename to core-management/core-management-subsystem/src/test/resources/org/wildfly/extension/core/management/core-management-1.0.xml index 75badc23690..7ab654653a6 100644 --- a/core-management/core-management-subsystem/src/test/resources/org/wildfly/extension/core/management/core-management-subsystem-1_0.xml +++ b/core-management/core-management-subsystem/src/test/resources/org/wildfly/extension/core/management/core-management-1.0.xml @@ -3,4 +3,6 @@ ~ SPDX-License-Identifier: Apache-2.0 --> + + \ No newline at end of file diff --git a/core-management/core-management-subsystem/src/test/resources/org/wildfly/extension/core/management/core-management-preview-1.0.xml b/core-management/core-management-subsystem/src/test/resources/org/wildfly/extension/core/management/core-management-preview-1.0.xml new file mode 100644 index 00000000000..89d671fd23b --- /dev/null +++ b/core-management/core-management-subsystem/src/test/resources/org/wildfly/extension/core/management/core-management-preview-1.0.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 43efcddba94..2ad1ff143dc 100644 --- a/pom.xml +++ b/pom.xml @@ -245,6 +245,7 @@ 2.4.2.Final 4.1.0.Final 3.0.3.Final + 1.0.0.Alpha3 2.2 @@ -2172,11 +2173,17 @@ + + org.wildfly.unstable.api.annotation + unstable-api-annotation-classpath-indexer + ${version.org.wildfly.unstable.api.annotation} + + org.yaml snakeyaml ${version.org.yaml.snakeyaml} - + org.jboss.logging jboss-logging-annotations diff --git a/server/src/main/java/org/jboss/as/server/deployment/Phase.java b/server/src/main/java/org/jboss/as/server/deployment/Phase.java index 3621ae8cf05..c8ed45ca3a4 100644 --- a/server/src/main/java/org/jboss/as/server/deployment/Phase.java +++ b/server/src/main/java/org/jboss/as/server/deployment/Phase.java @@ -248,6 +248,8 @@ public AttachmentKey getPhaseKey() { public static final int PARSE_COMPOSITE_ANNOTATION_INDEX = 0x0301; public static final int PARSE_EXTENSION_LIST = 0x0700; public static final int PARSE_EXTENSION_NAME = 0x0800; + public static final int PARSE_SCAN_EXPERIMENTAL_ANNOTATIONS = 0x0840; + public static final int PARSE_REPORT_EXPERIMENTAL_ANNOTATIONS = 0x0850; public static final int PARSE_WEB_DEPLOYMENT = 0x0B00; public static final int PARSE_WEB_DEPLOYMENT_FRAGMENT = 0x0C00; diff --git a/subsystem-test/framework/src/main/java/org/jboss/as/subsystem/test/AdditionalInitialization.java b/subsystem-test/framework/src/main/java/org/jboss/as/subsystem/test/AdditionalInitialization.java index fea289c8788..023d8a3fbfd 100644 --- a/subsystem-test/framework/src/main/java/org/jboss/as/subsystem/test/AdditionalInitialization.java +++ b/subsystem-test/framework/src/main/java/org/jboss/as/subsystem/test/AdditionalInitialization.java @@ -5,10 +5,6 @@ package org.jboss.as.subsystem.test; -import java.io.Serializable; -import java.util.List; -import java.util.Map; - import org.jboss.as.controller.FeatureRegistry; import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.ProcessType; @@ -29,6 +25,10 @@ import org.jboss.dmr.ModelType; import org.jboss.msc.service.ServiceTarget; +import java.io.Serializable; +import java.util.List; +import java.util.Map; + /** * Allows you to additionally initialize the service container and the model controller * beyond the subsystem being tested. Override this class to add behaviour. @@ -38,12 +38,7 @@ public class AdditionalInitialization extends AdditionalParsers implements FeatureRegistry { public static final AdditionalInitialization MANAGEMENT = new ManagementAdditionalInitialization(); - public static final AdditionalInitialization ADMIN_ONLY_HC = new ManagementAdditionalInitialization() { - @Override - protected ProcessType getProcessType() { - return ProcessType.HOST_CONTROLLER; - } - }; + public static final AdditionalInitialization ADMIN_ONLY_HC = new AdminOnlyHostControllerAdditionalInitialization(); public static class HostControllerAdditionalInitialization extends AdditionalInitialization implements Serializable { private static final long serialVersionUID = -509444465514822866L; @@ -96,6 +91,26 @@ protected RunningMode getRunningMode() { } } + public static class AdminOnlyHostControllerAdditionalInitialization extends ManagementAdditionalInitialization implements Serializable { + public AdminOnlyHostControllerAdditionalInitialization() { + super(); + } + + public > AdminOnlyHostControllerAdditionalInitialization(S schema) { + super(schema); + } + + public AdminOnlyHostControllerAdditionalInitialization(Stability stability) { + super(stability); + } + + @Override + protected ProcessType getProcessType() { + return ProcessType.HOST_CONTROLLER; + } + } + + /** * Creates a {@link org.jboss.as.subsystem.test.AdditionalInitialization.ManagementAdditionalInitialization} with * the given {@link org.jboss.as.controller.capability.RuntimeCapability capabilities} registered, making it diff --git a/testsuite/pom.xml b/testsuite/pom.xml index 0d64f23a552..4af49877963 100644 --- a/testsuite/pom.xml +++ b/testsuite/pom.xml @@ -53,6 +53,7 @@ elytron embedded scripts + unstable-api-annotation diff --git a/testsuite/unstable-api-annotation/feature-pack/feature-pack/pom.xml b/testsuite/unstable-api-annotation/feature-pack/feature-pack/pom.xml new file mode 100644 index 00000000000..06f63daafc7 --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/feature-pack/pom.xml @@ -0,0 +1,152 @@ + + + + 4.0.0 + + + org.wildfly.core + wildfly-core-testsuite-unstable-api-annotation-feature-pack-parent + 25.0.0.Beta5-SNAPSHOT + + + wildfly-core-testsuite-unstable-api-annotation-feature-pack + pom + + WildFly Core Test Suite: Unstable API Annotation Feature Pack + + + + + + ${artifactId}-${project.version} + + + + maven-clean-plugin + + + auto-clean + initialize + + clean + + + + + + org.wildfly.unstable.api.annotation + unstable-api-annotation-classpath-indexer-plugin + ${version.org.wildfly.unstable.api.annotation} + + + scan-experimental-annotations + compile + + index-unstable-api-annotations + + + ${project.build.directory}/index/wildfly-core-testsuite-unstable-api-annotation-feature-pack.txt + + + org.wildfly.core.test.unstable.api.annotation.classes.api.Unstable + + ${project.groupId} + + + + + + + + + org.apache.maven.plugins + maven-resources-plugin + + + copy-resources + process-resources + + copy-resources + + + ${basedir}/target/resources + + + ${basedir}/src/main/resources + + + + + + + + org.wildfly.galleon-plugins + wildfly-galleon-maven-plugin + ${version.org.wildfly.galleon-plugins} + + + wildfly-template-feature-pack-build + + build-feature-pack + + prepare-package + + ${galleon.fork.embedded} + + + + + + org.apache.maven.plugins + maven-resources-plugin + + + copy-annotation-index + prepare-package + + copy-resources + + + ${basedir}/target/resources/packages/unstable-api-annotation-index.wildfly-core-testsuite-unstable-api-annotation-feature-pack/content/ + + + ${basedir}/target/index/ + + + + + + + + + + + + + + org.wildfly.core + wildfly-core-galleon-pack + zip + + + + org.wildfly.galleon-plugins + wildfly-galleon-plugins + provided + + + + ${project.groupId} + wildfly-core-testsuite-unstable-api-annotation-feature-pack-subsystem + + + + + + diff --git a/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/configs/domain/model.xml b/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/configs/domain/model.xml new file mode 100644 index 00000000000..0c9a627fa34 --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/configs/domain/model.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/configs/host/model.xml b/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/configs/host/model.xml new file mode 100644 index 00000000000..3699b92e608 --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/configs/host/model.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + diff --git a/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/configs/standalone/model.xml b/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/configs/standalone/model.xml new file mode 100644 index 00000000000..dfe41dab468 --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/configs/standalone/model.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/feature_groups/unstable-api-annotation-test-subsystem.xml b/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/feature_groups/unstable-api-annotation-test-subsystem.xml new file mode 100644 index 00000000000..99420a52fa4 --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/feature_groups/unstable-api-annotation-test-subsystem.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/layers/standalone/unstable-api-annotation-test/layer-spec.xml b/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/layers/standalone/unstable-api-annotation-test/layer-spec.xml new file mode 100644 index 00000000000..412abd2d258 --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/layers/standalone/unstable-api-annotation-test/layer-spec.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/modules/system/layers/base/org/wildfly/core/test/extension/unstable-api-annotation-test-subsystem/main/module.xml b/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/modules/system/layers/base/org/wildfly/core/test/extension/unstable-api-annotation-test-subsystem/main/module.xml new file mode 100644 index 00000000000..43c3c4d077f --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/modules/system/layers/base/org/wildfly/core/test/extension/unstable-api-annotation-test-subsystem/main/module.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/packages/unstable-api-annotation-index.wildfly-core-testsuite-unstable-api-annotation-feature-pack/package.xml b/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/packages/unstable-api-annotation-index.wildfly-core-testsuite-unstable-api-annotation-feature-pack/package.xml new file mode 100644 index 00000000000..1afad183b75 --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/packages/unstable-api-annotation-index.wildfly-core-testsuite-unstable-api-annotation-feature-pack/package.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/packages/unstable-api-annotation-index.wildfly-core-testsuite-unstable-api-annotation-feature-pack/pm/wildfly/tasks.xml b/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/packages/unstable-api-annotation-index.wildfly-core-testsuite-unstable-api-annotation-feature-pack/pm/wildfly/tasks.xml new file mode 100644 index 00000000000..f396d92504b --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/feature-pack/src/main/resources/packages/unstable-api-annotation-index.wildfly-core-testsuite-unstable-api-annotation-feature-pack/pm/wildfly/tasks.xml @@ -0,0 +1,14 @@ + + + + + + wildfly-core-testsuite-unstable-api-annotation-feature-pack.txt + + + diff --git a/testsuite/unstable-api-annotation/feature-pack/feature-pack/wildfly-feature-pack-build.xml b/testsuite/unstable-api-annotation/feature-pack/feature-pack/wildfly-feature-pack-build.xml new file mode 100644 index 00000000000..d8f4fd8082c --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/feature-pack/wildfly-feature-pack-build.xml @@ -0,0 +1,26 @@ + + + + + org.wildfly:wildfly-ee-galleon-pack + + + + + + + + + + + + + org.wildfly.core.test.extension.unstable-api-annotation-test-subsystem + + + + \ No newline at end of file diff --git a/testsuite/unstable-api-annotation/feature-pack/pom.xml b/testsuite/unstable-api-annotation/feature-pack/pom.xml new file mode 100644 index 00000000000..f7f6fa9186c --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/pom.xml @@ -0,0 +1,46 @@ + + + + 4.0.0 + + + org.wildfly.core + wildfly-core-parent + 25.0.0.Beta5-SNAPSHOT + ../../../pom.xml + + + wildfly-core-testsuite-unstable-api-annotation-feature-pack-parent + pom + + WildFly Core Test Suite: Unstable API Annotation Feature Pack Parent + + + feature-pack + subsystem + + + + + + ${project.groupId} + wildfly-core-testsuite-unstable-api-annotation-feature-pack + ${project.version} + + + ${project.groupId} + wildfly-core-testsuite-unstable-api-annotation-feature-pack-subsystem + ${project.version} + + + + + + + + diff --git a/testsuite/unstable-api-annotation/feature-pack/subsystem/pom.xml b/testsuite/unstable-api-annotation/feature-pack/subsystem/pom.xml new file mode 100644 index 00000000000..9227de26073 --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/subsystem/pom.xml @@ -0,0 +1,58 @@ + + + + 4.0.0 + + + org.wildfly.core + wildfly-core-testsuite-unstable-api-annotation-feature-pack-parent + 25.0.0.Beta5-SNAPSHOT + + + wildfly-core-testsuite-unstable-api-annotation-feature-pack-subsystem + jar + + WildFly Core Test Suite: Unstable API Annotation Feature Pack Subsystem + + + + org.jboss.logging + jboss-logging + provided + + + + org.jboss.logging + jboss-logging-annotations + provided + true + + + + org.jboss.logging + jboss-logging-processor + provided + true + + + + ${project.groupId} + wildfly-controller + provided + + + + ${project.groupId} + wildfly-server + provided + + + + + + diff --git a/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/_private/UnstableAnnotationApiTestLogger.java b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/_private/UnstableAnnotationApiTestLogger.java new file mode 100644 index 00000000000..49ea16e7d24 --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/_private/UnstableAnnotationApiTestLogger.java @@ -0,0 +1,39 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.classes._private; + +import org.jboss.as.server.deployment.DeploymentUnitProcessingException; +import org.jboss.logging.BasicLogger; +import org.jboss.logging.Logger; +import org.jboss.logging.annotations.LogMessage; +import org.jboss.logging.annotations.Message; +import org.jboss.logging.annotations.MessageLogger; + +import static org.jboss.logging.Logger.Level.INFO; + +/** + * Log messages for our template subsystem. + * + * @author Kabir Khan (c) 2019 Red Hat inc. + */ +// TODO Make the projectCode in the @MessageLogger annotation some abbreviation to identify your subsystem +@MessageLogger(projectCode = "WFLYGPTMPL", length = 4) +// TODO Rename to something that makes sense for your subsystem. +public interface UnstableAnnotationApiTestLogger extends BasicLogger { + + UnstableAnnotationApiTestLogger LOGGER = Logger.getMessageLogger(UnstableAnnotationApiTestLogger.class, "org.wildfly.extension.galleon.pack.template.subsystem"); + + /** + * Logs an informational message indicating the subsystem is being activated. + */ + @LogMessage(level = INFO) + @Message(id = 1, value = "Activating Unstable Annotation API Subsystem") + void activatingSubsystem(); + + + @Message(id = 2, value = "Deployment %s requires use of the '%s' capability but it is not currently registered") + DeploymentUnitProcessingException deploymentRequiresCapability(String deploymentName, String capabilityName); +} diff --git a/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/AnnotatedAnnotation.java b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/AnnotatedAnnotation.java new file mode 100644 index 00000000000..f424dd8b0d7 --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/AnnotatedAnnotation.java @@ -0,0 +1,10 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.classes.api; + +@Unstable +public @interface AnnotatedAnnotation { +} diff --git a/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/TestClassWithAnnotatedField.java b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/TestClassWithAnnotatedField.java new file mode 100644 index 00000000000..02976461d5a --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/TestClassWithAnnotatedField.java @@ -0,0 +1,11 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.classes.api; + +public class TestClassWithAnnotatedField { + @Unstable + public static int annotatedField; +} diff --git a/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/TestClassWithAnnotatedMethod.java b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/TestClassWithAnnotatedMethod.java new file mode 100644 index 00000000000..cc8c8cc7ccf --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/TestClassWithAnnotatedMethod.java @@ -0,0 +1,12 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.classes.api; + +public class TestClassWithAnnotatedMethod { + @Unstable + public static void annotatedMethod() { + } +} diff --git a/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/TestClassWithAnnotationForExtends.java b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/TestClassWithAnnotationForExtends.java new file mode 100644 index 00000000000..aba3b2eca86 --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/TestClassWithAnnotationForExtends.java @@ -0,0 +1,10 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.classes.api; + +@Unstable +public class TestClassWithAnnotationForExtends { +} diff --git a/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/TestClassWithAnnotationForUsage.java b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/TestClassWithAnnotationForUsage.java new file mode 100644 index 00000000000..0b5c827a472 --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/TestClassWithAnnotationForUsage.java @@ -0,0 +1,13 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.classes.api; + +@Unstable +public class TestClassWithAnnotationForUsage { + public void methodWithNoAnnotation() { + + } +} diff --git a/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/TestInterfaceWithAnnotation.java b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/TestInterfaceWithAnnotation.java new file mode 100644 index 00000000000..891f1d38ecc --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/TestInterfaceWithAnnotation.java @@ -0,0 +1,10 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.classes.api; + +@Unstable +public interface TestInterfaceWithAnnotation { +} diff --git a/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/Unstable.java b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/Unstable.java new file mode 100644 index 00000000000..2c08a5d6f4a --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/api/Unstable.java @@ -0,0 +1,13 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.classes.api; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Unstable { +} diff --git a/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/subsystem/UnstableApiAnnotationTestDependencyProcessor.java b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/subsystem/UnstableApiAnnotationTestDependencyProcessor.java new file mode 100644 index 00000000000..6667fbb5a67 --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/subsystem/UnstableApiAnnotationTestDependencyProcessor.java @@ -0,0 +1,51 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.classes.subsystem; + +import org.jboss.as.server.deployment.Attachments; +import org.jboss.as.server.deployment.DeploymentPhaseContext; +import org.jboss.as.server.deployment.DeploymentUnit; +import org.jboss.as.server.deployment.DeploymentUnitProcessor; +import org.jboss.as.server.deployment.module.ModuleDependency; +import org.jboss.as.server.deployment.module.ModuleSpecification; +import org.jboss.modules.Module; +import org.jboss.modules.ModuleLoader; + +/** + * @author Kabir Khan + */ +public class UnstableApiAnnotationTestDependencyProcessor implements DeploymentUnitProcessor { + + @Override + public void deploy(DeploymentPhaseContext phaseContext) { + DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit(); + + addModuleDependencies(deploymentUnit); + } + + @Override + public void undeploy(DeploymentUnit context) { + } + + private void addModuleDependencies(DeploymentUnit deploymentUnit) { + final ModuleSpecification moduleSpecification = deploymentUnit.getAttachment(Attachments.MODULE_SPECIFICATION); + final ModuleLoader moduleLoader = Module.getBootModuleLoader(); + + // Pull in dependencies needed by deployments in the subsystem + + // This is needed if running with a security manager, and seems to be needed by arquillian in all cases + moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, "org.wildfly.security.manager", false, false, true, false)); + moduleSpecification.addSystemDependency( + cdiDependency(new ModuleDependency(moduleLoader, "org.wildfly.core.test.extension.unstable-api-annotation-test-subsystem", false, false, true, false))); + } + + + private ModuleDependency cdiDependency(ModuleDependency moduleDependency) { + // This is needed following https://issues.redhat.com/browse/WFLY-13641 / https://github.com/wildfly/wildfly/pull/13406 + moduleDependency.addImportFilter(s -> s.equals("META-INF"), true); + return moduleDependency; + } +} diff --git a/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/subsystem/UnstableApiAnnotationTestExtension.java b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/subsystem/UnstableApiAnnotationTestExtension.java new file mode 100644 index 00000000000..cb252b29149 --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/subsystem/UnstableApiAnnotationTestExtension.java @@ -0,0 +1,67 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.classes.subsystem; + +import org.jboss.as.controller.Extension; +import org.jboss.as.controller.ExtensionContext; +import org.jboss.as.controller.ModelVersion; +import org.jboss.as.controller.PathElement; +import org.jboss.as.controller.SubsystemRegistration; +import org.jboss.as.controller.descriptions.ResourceDescriptionResolver; +import org.jboss.as.controller.descriptions.StandardResourceDescriptionResolver; +import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler; +import org.jboss.as.controller.parsing.ExtensionParsingContext; +import org.jboss.as.controller.registry.ManagementResourceRegistration; + +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM; + +/** + * @author Kabir Khan + */ +public class UnstableApiAnnotationTestExtension implements Extension { + + public static final String SUBSYSTEM_NAME = "unstable-api-annotation-test"; + + protected static final PathElement SUBSYSTEM_PATH = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME); + + private static final String RESOURCE_NAME = UnstableApiAnnotationTestExtension.class.getPackage().getName() + ".LocalDescriptions"; + + protected static final ModelVersion VERSION_1_0_0 = ModelVersion.create(1, 0, 0); + private static final ModelVersion CURRENT_MODEL_VERSION = VERSION_1_0_0; + + private static final UnstableApiAnnotationTestSubsystemParser_1_0 CURRENT_PARSER = new UnstableApiAnnotationTestSubsystemParser_1_0(); + + static ResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) { + return getResourceDescriptionResolver(true, keyPrefix); + + } + + static ResourceDescriptionResolver getResourceDescriptionResolver(final boolean useUnprefixedChildTypes, final String... keyPrefix) { + StringBuilder prefix = new StringBuilder(); + for (String kp : keyPrefix) { + if (prefix.length() > 0){ + prefix.append('.'); + } + prefix.append(kp); + } + return new StandardResourceDescriptionResolver(prefix.toString(), RESOURCE_NAME, UnstableApiAnnotationTestExtension.class.getClassLoader(), true, useUnprefixedChildTypes); + } + + + @Override + public void initialize(ExtensionContext extensionContext) { + final SubsystemRegistration sr = extensionContext.registerSubsystem(SUBSYSTEM_NAME, CURRENT_MODEL_VERSION); + sr.registerXMLElementWriter(CURRENT_PARSER); + final ManagementResourceRegistration root = sr.registerSubsystemModel(new UnstableApiAnnotationTestSubsystemDefinition()); + root.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE, false); + } + + @Override + public void initializeParsers(ExtensionParsingContext extensionParsingContext) { + extensionParsingContext.setSubsystemXmlMapping(SUBSYSTEM_NAME, UnstableApiAnnotationTestSubsystemParser_1_0.NAMESPACE, CURRENT_PARSER); + } + +} diff --git a/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/subsystem/UnstableApiAnnotationTestSubsystemDefinition.java b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/subsystem/UnstableApiAnnotationTestSubsystemDefinition.java new file mode 100644 index 00000000000..10807f7ce28 --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/subsystem/UnstableApiAnnotationTestSubsystemDefinition.java @@ -0,0 +1,81 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.classes.subsystem; + +import org.jboss.as.controller.AbstractBoottimeAddStepHandler; +import org.jboss.as.controller.AttributeDefinition; +import org.jboss.as.controller.ModelOnlyRemoveStepHandler; +import org.jboss.as.controller.OperationContext; +import org.jboss.as.controller.OperationFailedException; +import org.jboss.as.controller.PersistentResourceDefinition; +import org.jboss.as.controller.capability.RuntimeCapability; +import org.jboss.as.controller.registry.ManagementResourceRegistration; +import org.jboss.as.server.AbstractDeploymentChainStep; +import org.jboss.as.server.DeploymentProcessorTarget; +import org.jboss.dmr.ModelNode; +import org.wildfly.core.test.unstable.api.annotation.classes._private.UnstableAnnotationApiTestLogger; + +import java.util.Collection; +import java.util.Collections; + +import static org.jboss.as.controller.OperationContext.Stage.RUNTIME; +import static org.jboss.as.server.deployment.Phase.DEPENDENCIES; + +/** + * @author Kabir Khan + */ +public class UnstableApiAnnotationTestSubsystemDefinition extends PersistentResourceDefinition { + + private static final String UNSTABLE_API_ANNOTATION_SUBSYSTEM_CAPABILITY_NAME = "org.wildfly.core.test.unstable-api-annotation"; + + private static final RuntimeCapability CONTEXT_PROPAGATION_CAPABILITY = RuntimeCapability.Builder + .of(UNSTABLE_API_ANNOTATION_SUBSYSTEM_CAPABILITY_NAME) + .build(); + + public UnstableApiAnnotationTestSubsystemDefinition() { + super( + new Parameters( + UnstableApiAnnotationTestExtension.SUBSYSTEM_PATH, + UnstableApiAnnotationTestExtension.getResourceDescriptionResolver(UnstableApiAnnotationTestExtension.SUBSYSTEM_NAME)) + .setAddHandler(AddHandler.INSTANCE) + .setRemoveHandler(new ModelOnlyRemoveStepHandler()) + .setCapabilities(CONTEXT_PROPAGATION_CAPABILITY) + ); + } + + @Override + public Collection getAttributes() { + return Collections.emptyList(); + } + + @Override + public void registerAdditionalRuntimePackages(ManagementResourceRegistration resourceRegistration) { + super.registerAdditionalRuntimePackages(resourceRegistration); + } + + static class AddHandler extends AbstractBoottimeAddStepHandler { + + static AddHandler INSTANCE = new AddHandler(); + + private AddHandler() { + super(); + } + + @Override + protected void performBoottime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException { + super.performBoottime(context, operation, model); + + context.addStep(new AbstractDeploymentChainStep() { + public void execute(DeploymentProcessorTarget processorTarget) { + final int DEPENDENCIES_TEMPLATE = 6304; + processorTarget.addDeploymentProcessor(UnstableApiAnnotationTestExtension.SUBSYSTEM_NAME, DEPENDENCIES, DEPENDENCIES_TEMPLATE, new UnstableApiAnnotationTestDependencyProcessor()); + } + }, RUNTIME); + + UnstableAnnotationApiTestLogger.LOGGER.activatingSubsystem(); + } + } +} diff --git a/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/subsystem/UnstableApiAnnotationTestSubsystemParser_1_0.java b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/subsystem/UnstableApiAnnotationTestSubsystemParser_1_0.java new file mode 100644 index 00000000000..e6491612060 --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/java/org/wildfly/core/test/unstable/api/annotation/classes/subsystem/UnstableApiAnnotationTestSubsystemParser_1_0.java @@ -0,0 +1,28 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.classes.subsystem; + +import org.jboss.as.controller.PersistentResourceXMLDescription; +import org.jboss.as.controller.PersistentResourceXMLParser; + +import static org.jboss.as.controller.PersistentResourceXMLDescription.builder; + +/** + * @author Kabir Khan + */ +public class UnstableApiAnnotationTestSubsystemParser_1_0 extends PersistentResourceXMLParser { + + public static final String NAMESPACE = "urn:wildfly:unstable-api-annotation-test-subsystem:1.0"; + + private static final PersistentResourceXMLDescription xmlDescription = builder(UnstableApiAnnotationTestExtension.SUBSYSTEM_PATH, NAMESPACE) + .build(); + + @Override + public PersistentResourceXMLDescription getParserDescription() { + return xmlDescription; + } + +} diff --git a/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/resources/META-INF/services/org.jboss.as.controller.Extension b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/resources/META-INF/services/org.jboss.as.controller.Extension new file mode 100644 index 00000000000..1c2251e9c8e --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/resources/META-INF/services/org.jboss.as.controller.Extension @@ -0,0 +1,6 @@ +# +# Copyright The WildFly Authors +# SPDX-License-Identifier: Apache-2.0 +# + +org.wildfly.core.test.unstable.api.annotation.classes.subsystem.UnstableApiAnnotationTestExtension diff --git a/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/resources/org/wildfly/core/test/unstable/api/annotation/classes/subsystem/LocalDescriptions.properties b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/resources/org/wildfly/core/test/unstable/api/annotation/classes/subsystem/LocalDescriptions.properties new file mode 100644 index 00000000000..e95404c5de2 --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/resources/org/wildfly/core/test/unstable/api/annotation/classes/subsystem/LocalDescriptions.properties @@ -0,0 +1,8 @@ +# +# Copyright The WildFly Authors +# SPDX-License-Identifier: Apache-2.0 +# + +unstable-api-annotation-test=The Unstable API Annotation Test subsystem +unstable-api-annotation-test.add=Adds the Unstable API Annotation Test subsystem +unstable-api-annotation-test.remove=Removes the Unstable API Annotation Test subsystem \ No newline at end of file diff --git a/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/resources/schema/unstable-annotation-api-test-subsystem_1_0.xsd b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/resources/schema/unstable-annotation-api-test-subsystem_1_0.xsd new file mode 100644 index 00000000000..ce7523e6c3b --- /dev/null +++ b/testsuite/unstable-api-annotation/feature-pack/subsystem/src/main/resources/schema/unstable-annotation-api-test-subsystem_1_0.xsd @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/testsuite/unstable-api-annotation/pom.xml b/testsuite/unstable-api-annotation/pom.xml new file mode 100644 index 00000000000..eb5692c5d09 --- /dev/null +++ b/testsuite/unstable-api-annotation/pom.xml @@ -0,0 +1,40 @@ + + + + + 4.0.0 + + + org.wildfly.core + wildfly-core-testsuite + 25.0.0.Beta5-SNAPSHOT + + + wildfly-core-testsuite-unstable-api-annotation + pom + + WildFly Core Test Suite: Unstable API Annotation Parent + + + feature-pack + tests + + + + + + ${project.groupId} + wildfly-core-testsuite-unstable-api-annotation-feature-pack + zip + test + ${project.version} + + + + + diff --git a/testsuite/unstable-api-annotation/tests/pom.xml b/testsuite/unstable-api-annotation/tests/pom.xml new file mode 100644 index 00000000000..5fe61c58b65 --- /dev/null +++ b/testsuite/unstable-api-annotation/tests/pom.xml @@ -0,0 +1,271 @@ + + + + + 4.0.0 + + + org.wildfly.core + wildfly-core-testsuite-unstable-api-annotation + 25.0.0.Beta5-SNAPSHOT + + + wildfly-core-testsuite-unstable-api-annotation-tests + jar + + WildFly Core Test Suite: Unstable API Annotation Tests + + + ${basedir}/.. + ${jbossas.ts.integ.dir}/.. + ${jbossas.ts.dir} + ${project.basedir}/target/wildfly-core + nothing-to-exclude + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${exclude.tests} + + false + + ${testLogToFile} + + + ${jvm.args.ip.client} ${jvm.args.timeouts} ${surefire.system.args} -Djava.util.logging.manager=org.jboss.logmanager.LogManager + + + ${wildfly.home} + + Hello world + + + + ${modular.jdk.args} -Dmaven.repo.local=${settings.localRepository} + ${wildfly.home} + + ${settings.localRepository} + -Dmaven.repo.local=${settings.localRepository} ${surefire.system.args} ${jvm.args.ip.server} ${jvm.args.security} ${jvm.args.other} ${jvm.args.timeouts} -Djbossas.ts.dir=${jbossas.ts.dir} + + + + + org.wildfly.plugins + wildfly-maven-plugin + + + server-provisioning + + provision + + compile + + ${project.build.directory}/${server.output.dir.prefix} + false + ${galleon.log.time} + true + true + + + ${galleon.fork.embedded} + passive+ + + + + org.wildfly.core + wildfly-core-galleon-pack + ${project.version} + false + false + + + org.jboss.as.patching.cli + + + product.conf + + + + org.wildfly.core + wildfly-core-testsuite-unstable-api-annotation-feature-pack + ${project.version} + false + false + + + + core-server + core-tools + deployment-scanner + unstable-api-annotation-test + + + + + + + + + + + + ${project.groupId} + wildfly-core-testsuite-unstable-api-annotation-feature-pack + zip + test + + + jakarta.inject + jakarta.inject-api + test + + + org.wildfly.core + wildfly-core-management-subsystem + test + + + + + + layers.profile + + + ts.layers + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + + slimmed-server-surefire + test + + test + + + + + org.wildfly.core.test.standalone.mgmt.api.core.ReadConfigAsFeaturesStandaloneTestCase.java + + org.jboss.as.test.integration.credential.store.ManagementAuthenticationUsersTestCase.java + + + + + + + + + + + + bootablejar.profile + + + ts.bootable + + + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + server-provisioning + + provision + + none + + + + + org.wildfly.plugins + wildfly-jar-maven-plugin + + + + bootable-jar-packaging + + package + + compile + + test-wildfly.jar + true + false + ${galleon.log.time} + true + + + ${galleon.fork.embedded} + + + + org.wildfly.core + wildfly-core-galleon-pack + ${project.version} + + + org.wildfly.core + wildfly-core-testsuite-unstable-api-annotation-feature-pack + ${project.version} + + + + core-server + core-tools + deployment-scanner + unstable-api-annotation-test + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + + bootable-server-surefire + test + + test + + + + true + ${project.build.directory}/test-wildfly.jar + ${project.build.directory}/${server.output.dir.prefix} + + + + + + + + + + diff --git a/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/UnstableApiAnnotationScannerTestCase.java b/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/UnstableApiAnnotationScannerTestCase.java new file mode 100644 index 00000000000..7d6caf9488f --- /dev/null +++ b/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/UnstableApiAnnotationScannerTestCase.java @@ -0,0 +1,333 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.reporter; + +import jakarta.inject.Inject; +import org.jboss.as.controller.PathAddress; +import org.jboss.as.controller.client.ModelControllerClient; +import org.jboss.as.controller.client.Operation; +import org.jboss.as.controller.operations.common.Util; +import org.jboss.as.test.integration.management.ManagementOperations; +import org.jboss.as.test.integration.management.util.MgmtOperationException; +import org.jboss.as.test.integration.management.util.ServerReload; +import org.jboss.dmr.ModelNode; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.exporter.ZipExporter; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.wildfly.core.test.unstable.api.annotation.classes.api.TestClassWithAnnotatedField; +import org.wildfly.core.test.unstable.api.annotation.classes.api.TestClassWithAnnotatedMethod; +import org.wildfly.core.test.unstable.api.annotation.classes.api.TestClassWithAnnotationForExtends; +import org.wildfly.core.test.unstable.api.annotation.classes.api.TestClassWithAnnotationForUsage; +import org.wildfly.core.test.unstable.api.annotation.classes.api.TestInterfaceWithAnnotation; +import org.wildfly.core.test.unstable.api.annotation.reporter.classes.AnnotatedAnnotationUsage; +import org.wildfly.core.test.unstable.api.annotation.reporter.classes.AnnotatedClassExtendsUsage; +import org.wildfly.core.test.unstable.api.annotation.reporter.classes.AnnotatedClassUsage; +import org.wildfly.core.test.unstable.api.annotation.reporter.classes.AnnotatedFieldUsage; +import org.wildfly.core.test.unstable.api.annotation.reporter.classes.AnnotatedInterfaceImplementsUsage; +import org.wildfly.core.test.unstable.api.annotation.reporter.classes.AnnotatedMethodUsage; +import org.wildfly.core.testrunner.ManagementClient; +import org.wildfly.core.testrunner.ServerSetup; +import org.wildfly.core.testrunner.ServerSetupTask; +import org.wildfly.core.testrunner.WildFlyRunner; +import org.wildfly.extension.core.management.CoreManagementExtension; +import org.wildfly.extension.core.management.UnstableApiAnnotationResourceDefinition; +import org.wildfly.test.stability.StabilityServerSetupSnapshotRestoreTasks; + +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FAILURE_DESCRIPTION; +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SYSTEM_PROPERTY; + +@RunWith(WildFlyRunner.class) +@ServerSetup({UnstableApiAnnotationScannerTestCase.AddUnstableApiAnnotationResourceSetupTask.class, UnstableApiAnnotationScannerTestCase.SystemPropertyServerSetupTask.class}) +public class UnstableApiAnnotationScannerTestCase { + + @Inject + private ManagementClient managementClient; + + private static final String INDEX_MODULE_DIR = + "system/layers/base/org/wildfly/_internal/unstable-api-annotation-index/main"; + + private static final String CONTENT = "content"; + private static final String INDEX_INDEX_FILE = "index.txt"; + + private static final String TEST_FEATURE_PACK_INDEX = "wildfly-core-testsuite-unstable-api-annotation-feature-pack.txt"; + + @Test + public void testIndexExists() throws Exception { + String jbossHomeProp = System.getProperty("jboss.home"); + + Path jbossHome = Paths.get(jbossHomeProp); + Assert.assertTrue(Files.exists(jbossHome)); + + Path modulesPath = jbossHome.resolve("modules"); + Assert.assertTrue(Files.exists(modulesPath)); + + Path indexModulePath = modulesPath.resolve(INDEX_MODULE_DIR); + Assert.assertTrue(Files.exists(indexModulePath)); + + Path indexContentDir = indexModulePath.resolve(CONTENT); + Assert.assertTrue(Files.exists(indexContentDir)); + + Path mainIndexFile = indexContentDir.resolve(INDEX_INDEX_FILE); + Assert.assertTrue(Files.exists(mainIndexFile)); + + List mainIndexFileList = Files.readAllLines(mainIndexFile) + .stream() + .filter(s -> !s.isEmpty()) + .filter(s -> !s.startsWith("#")) + .collect(Collectors.toList()); + + Assert.assertEquals(1, mainIndexFileList.size()); + Assert.assertTrue(mainIndexFileList.contains(TEST_FEATURE_PACK_INDEX)); + + Set indices = Files.list(indexContentDir) + .filter(p -> !p.getFileName().toString().equals(INDEX_INDEX_FILE)) + .map(p -> p.getFileName().toString()) + .collect(Collectors.toSet()); + + Assert.assertEquals(1, indices.size()); + Assert.assertTrue(indices.toString(), indices.contains(TEST_FEATURE_PACK_INDEX)); + } + + @Test + public void testDeploymentWarning() throws Exception { + LogDiffer logDiffer = new LogDiffer(); + logDiffer.takeSnapshot(); + + + JavaArchive deployment = createDeploymentWithUnstableAnnotations(); + ModelControllerClient mcc = managementClient.getControllerClient(); + Operation deploymentOp = createDeploymentOp(deployment); + + try { + ManagementOperations.executeOperation(mcc, deploymentOp); + List newLogEntries = logDiffer.getNewLogEntries(); + Assert.assertFalse(newLogEntries.isEmpty()); + Assert.assertEquals(8, newLogEntries.size()); + checkExpectedNumberClasses(newLogEntries, 6); + + checkLogOrErrorLines(newLogEntries); + } finally { + ManagementOperations.executeOperation(mcc, Util.createRemoveOperation(PathAddress.pathAddress("deployment", deployment.getName()))); + } + + } + + @Test + public void testDeploymentError() throws Exception{ + JavaArchive deployment = createDeploymentWithUnstableAnnotations(); + ModelControllerClient mcc = managementClient.getControllerClient(); + + PathAddress address = PathAddress.pathAddress(CoreManagementExtension.SUBSYSTEM_PATH) + .append(UnstableApiAnnotationResourceDefinition.PATH); + ModelNode writeAttributeOp = Util.getWriteAttributeOperation(address, + UnstableApiAnnotationResourceDefinition.LEVEL.getName(), + UnstableApiAnnotationResourceDefinition.UnstableApiAnnotationLevel.ERROR.toString()); + try { + ManagementOperations.executeOperation(mcc, writeAttributeOp); + ServerReload.executeReloadAndWaitForCompletion(mcc, false); + + boolean deployed = false; + Operation deploymentOp = createDeploymentOp(deployment); + try { + ManagementOperations.executeOperation(mcc, deploymentOp); + deployed = true; + Assert.fail("Expected deployment to fail"); + } catch (MgmtOperationException expected) { + String error = expected.getResult().get(FAILURE_DESCRIPTION).asString(); + List lines = Arrays.asList(error.split("\n")); + + + } finally { + if (deployed) { + ManagementOperations.executeOperation(mcc, Util.createRemoveOperation(PathAddress.pathAddress("deployment", deployment.getName()))); + } + } + + + } finally { + ManagementOperations.executeOperation(mcc, Util.getUndefineAttributeOperation(address, UnstableApiAnnotationResourceDefinition.LEVEL.getName())); + ServerReload.executeReloadAndWaitForCompletion(mcc, false); + } + + LogDiffer logDiffer = new LogDiffer(); + logDiffer.takeSnapshot(); + // Deploy a deployment with unstable annotations + // Check that the log contains the expected warning + } + + @Test + public void testNoWarmingIfUnstableApiAnnotationResourceIsNotDefined() throws Exception { + + + PathAddress address = PathAddress.pathAddress(CoreManagementExtension.SUBSYSTEM_PATH) + .append(UnstableApiAnnotationResourceDefinition.PATH); + ModelNode removeOp = Util.createRemoveOperation(address); + ManagementOperations.executeOperation(managementClient.getControllerClient(), removeOp); + try { + ServerReload.executeReloadAndWaitForCompletion(managementClient.getControllerClient()); + + LogDiffer logDiffer = new LogDiffer(); + logDiffer.takeSnapshot(); + + JavaArchive deployment = createDeploymentWithUnstableAnnotations(); + ModelControllerClient mcc = managementClient.getControllerClient(); + Operation deploymentOp = createDeploymentOp(deployment); + + try { + ManagementOperations.executeOperation(mcc, deploymentOp); + List newLogEntries = logDiffer.getNewLogEntries(); + Assert.assertTrue(newLogEntries.isEmpty()); + } finally { + ManagementOperations.executeOperation(mcc, Util.createRemoveOperation(PathAddress.pathAddress("deployment", deployment.getName()))); + } + + } finally { + ModelNode addOp = Util.createAddOperation(address); + ManagementOperations.executeOperation(managementClient.getControllerClient(), addOp); + ServerReload.executeReloadAndWaitForCompletion(managementClient.getControllerClient()); + } + } + + private void checkLogOrErrorLines(List lines) { + checkLogLine(lines.get(1), "WFLYCM0009", "deployment-with-unstable-annotations.jar"); + checkLogLine(lines.get(2), "WFLYCM0010", + AnnotatedClassExtendsUsage.class.getName(), + TestClassWithAnnotationForExtends.class.getName()); + checkLogLine(lines.get(3), "WFLYCM0011", + AnnotatedInterfaceImplementsUsage.class.getName(), + TestInterfaceWithAnnotation.class.getName()); + checkLogLine(lines.get(4), "WFLYCM0012", + AnnotatedFieldUsage.class.getName(), + TestClassWithAnnotatedField.class.getName() + ".annotatedField"); + checkLogLine(lines.get(5), "WFLYCM0013", + AnnotatedMethodUsage.class.getName(), + TestClassWithAnnotatedMethod.class.getName() + ".annotatedMethod()V"); + checkLogLine(lines.get(6), "WFLYCM0014", + AnnotatedClassUsage.class.getName(), + TestClassWithAnnotationForUsage.class.getName()); + checkLogLine(lines.get(7), "WFLYCM0015", + AnnotatedAnnotationUsage.class.getName()); + } + + + + private void checkExpectedNumberClasses(List newLogEntries, int numberClasses) { + Assert.assertTrue(!newLogEntries.isEmpty()); + String last = newLogEntries.get(0); + checkLogLine(last, "WFLYCM0016", String.valueOf(numberClasses)); + } + + private void checkLogLine(String logLine, String loggingId, String...values) { + int index = logLine.indexOf(loggingId); + Assert.assertTrue("'" + logLine + "' does not contain '" + loggingId + "'",index != -1); + index += loggingId.length(); + Assert.assertTrue(index < logLine.length()); + String valuesPart = logLine.substring(index); + Set words = new HashSet<>(Arrays.asList(logLine.split(" "))); + for (String value : values) { + Assert.assertTrue("'" + logLine + "' does not contain '" + value + "'", words.contains(value)); + } + } + + private JavaArchive createDeploymentWithUnstableAnnotations() { + JavaArchive archive = ShrinkWrap.create(JavaArchive.class, "deployment-with-unstable-annotations.jar") + .addPackage(AnnotatedClassExtendsUsage.class.getPackage()); + + return archive; + } + + private Operation createDeploymentOp(JavaArchive deployment) { + final List streams = new ArrayList<>(); + streams.add(deployment.as(ZipExporter.class).exportAsInputStream()); + final ModelNode addOperation = Util.createAddOperation(PathAddress.pathAddress("deployment", deployment.getName())); + addOperation.get("enabled").set(true); + addOperation.get("content").add().get("input-stream-index").set(0); + return Operation.Factory.create(addOperation, streams, true); + } + + private static class LogDiffer { + Path logFile; + + private List lastLogSnapshot = Collections.emptyList(); + + + public LogDiffer() { + String jbossHomeProp = System.getProperty("jboss.home"); + Path jbossHome = Paths.get(jbossHomeProp); + Assert.assertTrue(Files.exists(jbossHome)); + this.logFile = jbossHome.resolve("standalone/log/server.log"); + Assert.assertTrue(Files.exists(logFile)); + } + + public void takeSnapshot() { + try { + lastLogSnapshot = Files.readAllLines(logFile); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public List getNewLogEntries() { + try { + List currentLog = Files.readAllLines(logFile); + return currentLog.stream() + .filter(s -> !lastLogSnapshot.contains(s)) + .filter(s -> s.contains("WFLYCM")) + .collect(Collectors.toList()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + } + + + public static class AddUnstableApiAnnotationResourceSetupTask extends StabilityServerSetupSnapshotRestoreTasks.Preview { + @Override + public void doSetup(ManagementClient managementClient) throws Exception { + PathAddress address = PathAddress.pathAddress(CoreManagementExtension.SUBSYSTEM_PATH) + .append(UnstableApiAnnotationResourceDefinition.PATH); + ModelNode addOp = Util.createAddOperation(address); + ManagementOperations.executeOperation(managementClient.getControllerClient(), addOp); + ServerReload.executeReloadAndWaitForCompletion(managementClient.getControllerClient()); + } + } + + + public static class SystemPropertyServerSetupTask implements ServerSetupTask { + @Override + public void setup(ManagementClient managementClient) throws Exception { + ModelNode op = Util.createAddOperation(PathAddress.pathAddress(SYSTEM_PROPERTY, "org.wildfly.test.unstable-api-annotation.extra-output")); + op.get("value").set("true"); + ManagementOperations.executeOperation(managementClient.getControllerClient(), op); + // Reload so the system property is picked up by the deployer in order to print extra information + // about class count + ServerReload.executeReloadAndWaitForCompletion(managementClient.getControllerClient()); + } + + @Override + public void tearDown(ManagementClient managementClient) throws Exception { + ModelNode op = Util.createAddOperation(PathAddress.pathAddress(SYSTEM_PROPERTY, "org.wildfly.test.unstable-api-annotation.extra-output")); + op.get("value").set("true"); + managementClient.getControllerClient().execute(op); + } + } +} diff --git a/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedAnnotationUsage.java b/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedAnnotationUsage.java new file mode 100644 index 00000000000..a7fb3d13a17 --- /dev/null +++ b/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedAnnotationUsage.java @@ -0,0 +1,13 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.reporter.classes; + + +import org.wildfly.core.test.unstable.api.annotation.classes.api.AnnotatedAnnotation; + +@AnnotatedAnnotation +public class AnnotatedAnnotationUsage { +} diff --git a/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedClassExtendsUsage.java b/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedClassExtendsUsage.java new file mode 100644 index 00000000000..5b3dc407fee --- /dev/null +++ b/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedClassExtendsUsage.java @@ -0,0 +1,12 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.reporter.classes; + +import org.wildfly.core.test.unstable.api.annotation.classes.api.TestClassWithAnnotationForExtends; + +public class AnnotatedClassExtendsUsage extends TestClassWithAnnotationForExtends { + +} diff --git a/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedClassUsage.java b/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedClassUsage.java new file mode 100644 index 00000000000..fb1b61ba082 --- /dev/null +++ b/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedClassUsage.java @@ -0,0 +1,17 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.reporter.classes; + +import org.wildfly.core.test.unstable.api.annotation.classes.api.TestClassWithAnnotationForUsage; +import org.wildfly.core.test.unstable.api.annotation.classes.api.Unstable; + +@Unstable +public class AnnotatedClassUsage { + + public void test(TestClassWithAnnotationForUsage clazz) { + clazz.methodWithNoAnnotation(); + } +} diff --git a/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedFieldUsage.java b/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedFieldUsage.java new file mode 100644 index 00000000000..29855bf8daf --- /dev/null +++ b/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedFieldUsage.java @@ -0,0 +1,15 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.reporter.classes; + +import org.wildfly.core.test.unstable.api.annotation.classes.api.TestClassWithAnnotatedField; + +public class AnnotatedFieldUsage { + + public void test() { + TestClassWithAnnotatedField.annotatedField = 10; + } +} diff --git a/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedInterfaceImplementsUsage.java b/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedInterfaceImplementsUsage.java new file mode 100644 index 00000000000..50a530cb649 --- /dev/null +++ b/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedInterfaceImplementsUsage.java @@ -0,0 +1,13 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.reporter.classes; + +import org.wildfly.core.test.unstable.api.annotation.classes.api.TestInterfaceWithAnnotation; + +public class AnnotatedInterfaceImplementsUsage implements TestInterfaceWithAnnotation { + + +} diff --git a/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedMethodUsage.java b/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedMethodUsage.java new file mode 100644 index 00000000000..f6107bb3d54 --- /dev/null +++ b/testsuite/unstable-api-annotation/tests/src/test/java/org/wildfly/core/test/unstable/api/annotation/reporter/classes/AnnotatedMethodUsage.java @@ -0,0 +1,14 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.wildfly.core.test.unstable.api.annotation.reporter.classes; + +import org.wildfly.core.test.unstable.api.annotation.classes.api.TestClassWithAnnotatedMethod; + +public class AnnotatedMethodUsage { + public void test() { + TestClassWithAnnotatedMethod.annotatedMethod(); + } +}