diff --git a/hadoop-hdds/annotations/src/main/java/org/apache/ozone/annotations/CliOptionStyleProcessor.java b/hadoop-hdds/annotations/src/main/java/org/apache/ozone/annotations/CliOptionStyleProcessor.java new file mode 100644 index 000000000000..0aec138dd7d0 --- /dev/null +++ b/hadoop-hdds/annotations/src/main/java/org/apache/ozone/annotations/CliOptionStyleProcessor.java @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ozone.annotations; + +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; +import java.util.regex.Pattern; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.util.SimpleAnnotationValueVisitor8; +import javax.tools.Diagnostic; + +/** + * Validates that picocli options use the preferred Ozone CLI option style. + */ +@SupportedAnnotationTypes(CliOptionStyleProcessor.OPTION_ANNOTATION) +public class CliOptionStyleProcessor extends AbstractProcessor { + + static final String OPTION_ANNOTATION = "picocli.CommandLine.Option"; + private static final String NAMES_ATTRIBUTE = "names"; + private static final Pattern CAMEL_CASE = Pattern.compile("--.*[A-Z].*"); + private static final Pattern UNDER_SCORE = Pattern.compile("--.*_.*"); + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latestSupported(); + } + + @Override + public boolean process(Set annotations, + RoundEnvironment roundEnv) { + for (TypeElement annotation : annotations) { + if (OPTION_ANNOTATION.contentEquals(annotation.getQualifiedName())) { + roundEnv.getElementsAnnotatedWith(annotation) + .forEach(this::checkOptionNames); + } + } + return false; + } + + private void checkOptionNames(Element element) { + for (AnnotationMirror annotation : element.getAnnotationMirrors()) { + if (isOptionAnnotation(annotation)) { + checkOptionNames(element, annotation); + } + } + } + + private boolean isOptionAnnotation(AnnotationMirror annotation) { + return OPTION_ANNOTATION.contentEquals( + annotation.getAnnotationType().asElement().toString()); + } + + private void checkOptionNames(Element element, AnnotationMirror annotation) { + for (Entry entry : + annotation.getElementValues().entrySet()) { + if (entry.getKey().getSimpleName().contentEquals(NAMES_ATTRIBUTE)) { + checkOptionNameValues(element, annotation, entry.getValue()); + } + } + } + + private void checkOptionNameValues(Element element, AnnotationMirror annotation, + AnnotationValue value) { + value.accept(new SimpleAnnotationValueVisitor8() { + @Override + public Void visitArray(List values, + Void unused) { + values.forEach(v -> checkOptionNameValues(element, annotation, v)); + return null; + } + + @Override + public Void visitString(String option, Void unused) { + checkOptionName(option, element, annotation, value); + return null; + } + }, null); + } + + private void checkOptionName(String option, Element element, + AnnotationMirror annotation, AnnotationValue value) { + if (hasDeprecatedStyle(option)) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, + String.format("CLI option '%s' uses a deprecated style. New options " + + "should use --dash-separated-style long names or " + + "single-character short names.", option), + element, annotation, value); + } + } + + private static boolean hasDeprecatedStyle(String option) { + if (option.startsWith("--")) { + return CAMEL_CASE.matcher(option).matches() + || UNDER_SCORE.matcher(option).matches(); + } + return option.startsWith("-") && option.length() > 2; + } + +} diff --git a/hadoop-hdds/cli-common/pom.xml b/hadoop-hdds/cli-common/pom.xml index 38de9741a1e7..1ace7bb68ac9 100644 --- a/hadoop-hdds/cli-common/pom.xml +++ b/hadoop-hdds/cli-common/pom.xml @@ -51,6 +51,11 @@ org.slf4j slf4j-api + + org.apache.ozone + hdds-annotation-processing + provided + @@ -67,6 +72,11 @@ maven-compiler-plugin + + org.apache.ozone + hdds-annotation-processing + ${hdds.version} + org.kohsuke.metainf-services metainf-services @@ -80,6 +90,7 @@ org.kohsuke.metainf_services.AnnotationProcessorImpl + org.apache.ozone.annotations.CliOptionStyleProcessor picocli.codegen.aot.graalvm.processor.NativeImageConfigGeneratorProcessor diff --git a/hadoop-hdds/server-scm/pom.xml b/hadoop-hdds/server-scm/pom.xml index 8c5293d9efa3..5a8a779e4e25 100644 --- a/hadoop-hdds/server-scm/pom.xml +++ b/hadoop-hdds/server-scm/pom.xml @@ -169,6 +169,11 @@ org.slf4j slf4j-api + + org.apache.ozone + hdds-annotation-processing + provided + org.apache.ozone hdds-docs @@ -255,6 +260,7 @@ org.apache.hadoop.hdds.conf.ConfigFileGenerator + org.apache.ozone.annotations.CliOptionStyleProcessor org.apache.ozone.annotations.ReplicateAnnotationProcessor diff --git a/hadoop-ozone/cli-admin/pom.xml b/hadoop-ozone/cli-admin/pom.xml index 0fad986a5b89..a9fbfe69280e 100644 --- a/hadoop-ozone/cli-admin/pom.xml +++ b/hadoop-ozone/cli-admin/pom.xml @@ -128,6 +128,11 @@ org.slf4j slf4j-api + + org.apache.ozone + hdds-annotation-processing + provided + org.kohsuke.metainf-services @@ -166,6 +171,11 @@ maven-compiler-plugin + + org.apache.ozone + hdds-annotation-processing + ${hdds.version} + org.kohsuke.metainf-services metainf-services @@ -179,6 +189,7 @@ org.kohsuke.metainf_services.AnnotationProcessorImpl + org.apache.ozone.annotations.CliOptionStyleProcessor picocli.codegen.aot.graalvm.processor.NativeImageConfigGeneratorProcessor diff --git a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/LifecycleResumeSubCommand.java b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/LifecycleResumeSubCommand.java index 69f6c66a90da..a25840ced707 100644 --- a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/LifecycleResumeSubCommand.java +++ b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/LifecycleResumeSubCommand.java @@ -38,13 +38,13 @@ public class LifecycleResumeSubCommand implements Callable { private LifecycleSubCommand parent; @CommandLine.Option( - names = {"-id", "--service-id"}, + names = {"--service-id"}, description = "Ozone Manager Service ID" ) private String omServiceId; @CommandLine.Option( - names = {"-host", "--service-host"}, + names = {"--service-host"}, description = "Ozone Manager Host" ) private String omHost; @@ -70,4 +70,3 @@ protected PrintStream out() { return System.out; } } - diff --git a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/LifecycleStatusSubCommand.java b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/LifecycleStatusSubCommand.java index a443471391ac..ea0ce071c55d 100644 --- a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/LifecycleStatusSubCommand.java +++ b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/LifecycleStatusSubCommand.java @@ -39,13 +39,13 @@ public class LifecycleStatusSubCommand implements Callable { private LifecycleSubCommand parent; @CommandLine.Option( - names = {"-id", "--service-id"}, + names = {"--service-id"}, description = "Ozone Manager Service ID" ) private String omServiceId; @CommandLine.Option( - names = {"-host", "--service-host"}, + names = {"--service-host"}, description = "Ozone Manager Host" ) private String omHost; @@ -86,4 +86,3 @@ protected PrintStream out() { return System.out; } } - diff --git a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/LifecycleSuspendSubCommand.java b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/LifecycleSuspendSubCommand.java index 8a420c3d41b6..86d4513d5884 100644 --- a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/LifecycleSuspendSubCommand.java +++ b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/LifecycleSuspendSubCommand.java @@ -39,13 +39,13 @@ public class LifecycleSuspendSubCommand implements Callable { private LifecycleSubCommand parent; @CommandLine.Option( - names = {"-id", "--service-id"}, + names = {"--service-id"}, description = "Ozone Manager Service ID" ) private String omServiceId; @CommandLine.Option( - names = {"-host", "--service-host"}, + names = {"--service-host"}, description = "Ozone Manager Host" ) private String omHost; @@ -73,4 +73,3 @@ protected PrintStream out() { return System.out; } } - diff --git a/hadoop-ozone/cli-debug/pom.xml b/hadoop-ozone/cli-debug/pom.xml index 63b54ec94b65..f7d574804c2d 100644 --- a/hadoop-ozone/cli-debug/pom.xml +++ b/hadoop-ozone/cli-debug/pom.xml @@ -204,6 +204,11 @@ org.xerial sqlite-jdbc + + org.apache.ozone + hdds-annotation-processing + provided + org.kohsuke.metainf-services @@ -262,6 +267,11 @@ maven-compiler-plugin + + org.apache.ozone + hdds-annotation-processing + ${hdds.version} + org.kohsuke.metainf-services metainf-services @@ -275,6 +285,7 @@ org.kohsuke.metainf_services.AnnotationProcessorImpl + org.apache.ozone.annotations.CliOptionStyleProcessor picocli.codegen.aot.graalvm.processor.NativeImageConfigGeneratorProcessor diff --git a/hadoop-ozone/cli-repair/pom.xml b/hadoop-ozone/cli-repair/pom.xml index 1e79d1ad13ed..9d83143d3a0c 100644 --- a/hadoop-ozone/cli-repair/pom.xml +++ b/hadoop-ozone/cli-repair/pom.xml @@ -138,6 +138,11 @@ org.slf4j slf4j-api + + org.apache.ozone + hdds-annotation-processing + provided + org.kohsuke.metainf-services @@ -201,6 +206,11 @@ maven-compiler-plugin + + org.apache.ozone + hdds-annotation-processing + ${hdds.version} + org.kohsuke.metainf-services metainf-services @@ -214,6 +224,7 @@ org.kohsuke.metainf_services.AnnotationProcessorImpl + org.apache.ozone.annotations.CliOptionStyleProcessor picocli.codegen.aot.graalvm.processor.NativeImageConfigGeneratorProcessor diff --git a/hadoop-ozone/cli-shell/pom.xml b/hadoop-ozone/cli-shell/pom.xml index 015ad13b59b0..b03bbe033d6c 100644 --- a/hadoop-ozone/cli-shell/pom.xml +++ b/hadoop-ozone/cli-shell/pom.xml @@ -115,6 +115,11 @@ org.slf4j slf4j-api + + org.apache.ozone + hdds-annotation-processing + provided + org.kohsuke.metainf-services @@ -154,6 +159,11 @@ maven-compiler-plugin + + org.apache.ozone + hdds-annotation-processing + ${hdds.version} + org.kohsuke.metainf-services metainf-services @@ -167,6 +177,7 @@ org.kohsuke.metainf_services.AnnotationProcessorImpl + org.apache.ozone.annotations.CliOptionStyleProcessor picocli.codegen.aot.graalvm.processor.NativeImageConfigGeneratorProcessor diff --git a/hadoop-ozone/freon/pom.xml b/hadoop-ozone/freon/pom.xml index 9bde7cf33956..9637ec3200d0 100644 --- a/hadoop-ozone/freon/pom.xml +++ b/hadoop-ozone/freon/pom.xml @@ -138,6 +138,11 @@ org.slf4j slf4j-api + + org.apache.ozone + hdds-annotation-processing + provided + org.kohsuke.metainf-services @@ -166,6 +171,11 @@ maven-compiler-plugin + + org.apache.ozone + hdds-annotation-processing + ${hdds.version} + org.kohsuke.metainf-services metainf-services @@ -179,6 +189,7 @@ org.kohsuke.metainf_services.AnnotationProcessorImpl + org.apache.ozone.annotations.CliOptionStyleProcessor picocli.codegen.aot.graalvm.processor.NativeImageConfigGeneratorProcessor diff --git a/hadoop-ozone/iceberg/pom.xml b/hadoop-ozone/iceberg/pom.xml index d881afce137c..8171192901e4 100644 --- a/hadoop-ozone/iceberg/pom.xml +++ b/hadoop-ozone/iceberg/pom.xml @@ -109,7 +109,6 @@ - org.apache.ozone hdds-cli-common @@ -127,6 +126,12 @@ org.slf4j slf4j-api + + + org.apache.ozone + hdds-annotation-processing + provided + org.apache.hadoop hadoop-mapreduce-client-core @@ -208,7 +213,16 @@ org.apache.maven.plugins maven-compiler-plugin - none + + + org.apache.ozone + hdds-annotation-processing + ${hdds.version} + + + + org.apache.ozone.annotations.CliOptionStyleProcessor + diff --git a/hadoop-ozone/insight/pom.xml b/hadoop-ozone/insight/pom.xml index 35f4f67b8a0b..cc68cb5fe7ac 100644 --- a/hadoop-ozone/insight/pom.xml +++ b/hadoop-ozone/insight/pom.xml @@ -100,6 +100,11 @@ jakarta.xml.bind-api provided + + org.apache.ozone + hdds-annotation-processing + provided + org.glassfish.jaxb jaxb-runtime @@ -126,8 +131,16 @@ org.apache.maven.plugins maven-compiler-plugin - - none + + + org.apache.ozone + hdds-annotation-processing + ${hdds.version} + + + + org.apache.ozone.annotations.CliOptionStyleProcessor + diff --git a/hadoop-ozone/ozone-manager/pom.xml b/hadoop-ozone/ozone-manager/pom.xml index 169751a8eb8a..0715e3e95630 100644 --- a/hadoop-ozone/ozone-manager/pom.xml +++ b/hadoop-ozone/ozone-manager/pom.xml @@ -233,6 +233,11 @@ org.yaml snakeyaml + + org.apache.ozone + hdds-annotation-processing + provided + org.apache.ozone hdds-docs @@ -266,11 +271,6 @@ test-jar test - - org.apache.ozone - hdds-annotation-processing - test - org.apache.ozone hdds-common @@ -334,6 +334,7 @@ org.apache.hadoop.hdds.conf.ConfigFileGenerator + org.apache.ozone.annotations.CliOptionStyleProcessor org.apache.ozone.annotations.OmRequestFeatureValidatorProcessor org.apache.ozone.annotations.RegisterValidatorProcessor diff --git a/hadoop-ozone/tools/pom.xml b/hadoop-ozone/tools/pom.xml index 3ffab37b2b24..9e26438e94fa 100644 --- a/hadoop-ozone/tools/pom.xml +++ b/hadoop-ozone/tools/pom.xml @@ -98,6 +98,11 @@ org.slf4j slf4j-api + + org.apache.ozone + hdds-annotation-processing + provided + org.kohsuke.metainf-services @@ -173,6 +178,11 @@ maven-compiler-plugin + + org.apache.ozone + hdds-annotation-processing + ${hdds.version} + org.kohsuke.metainf-services metainf-services @@ -186,6 +196,7 @@ org.kohsuke.metainf_services.AnnotationProcessorImpl + org.apache.ozone.annotations.CliOptionStyleProcessor picocli.codegen.aot.graalvm.processor.NativeImageConfigGeneratorProcessor diff --git a/hadoop-ozone/vapor/pom.xml b/hadoop-ozone/vapor/pom.xml index 78342bc6b0a3..41f7132fa3fb 100644 --- a/hadoop-ozone/vapor/pom.xml +++ b/hadoop-ozone/vapor/pom.xml @@ -150,6 +150,11 @@ org.slf4j slf4j-api + + org.apache.ozone + hdds-annotation-processing + provided + org.kohsuke.metainf-services @@ -178,6 +183,11 @@ maven-compiler-plugin + + org.apache.ozone + hdds-annotation-processing + ${hdds.version} + org.kohsuke.metainf-services metainf-services @@ -191,6 +201,7 @@ org.kohsuke.metainf_services.AnnotationProcessorImpl + org.apache.ozone.annotations.CliOptionStyleProcessor picocli.codegen.aot.graalvm.processor.NativeImageConfigGeneratorProcessor