From 3770c71abcd3f48f502537be9f7b5d5dcbb4d52d Mon Sep 17 00:00:00 2001 From: Swaminathan Balachandran Date: Fri, 20 Dec 2024 16:22:22 -0800 Subject: [PATCH 1/2] HDDS-11981. Add annotation for registering feature validator based on a generic version Change-Id: I0b86b27642a39595f12aee62638a1ea0f5410b14 --- ...> OmRequestFeatureValidatorProcessor.java} | 47 +- .../RegisterValidatorProcessor.java | 142 +++++ .../request/validation/RegisterValidator.java | 41 ++ .../validation/RequestProcessingPhase.java | 2 +- .../request/validation/package-info.java | 40 ++ hadoop-ozone/ozone-manager/pom.xml | 3 +- .../request/bucket/OMBucketCreateRequest.java | 2 +- .../request/bucket/OMBucketDeleteRequest.java | 2 +- .../bucket/OMBucketSetPropertyRequest.java | 2 +- .../file/OMDirectoryCreateRequest.java | 2 +- .../om/request/file/OMFileCreateRequest.java | 2 +- .../request/key/OMAllocateBlockRequest.java | 2 +- .../om/request/key/OMKeyCommitRequest.java | 2 +- .../om/request/key/OMKeyCreateRequest.java | 2 +- .../om/request/key/OMKeyDeleteRequest.java | 2 +- .../om/request/key/OMKeyRenameRequest.java | 2 +- .../om/request/key/OMKeysDeleteRequest.java | 2 +- .../om/request/key/OMKeysRenameRequest.java | 2 +- .../request/key/acl/OMKeyAddAclRequest.java | 2 +- .../key/acl/OMKeyRemoveAclRequest.java | 2 +- .../request/key/acl/OMKeySetAclRequest.java | 2 +- .../S3InitiateMultipartUploadRequest.java | 2 +- .../S3MultipartUploadAbortRequest.java | 2 +- .../S3MultipartUploadCommitPartRequest.java | 2 +- .../S3MultipartUploadCompleteRequest.java | 2 +- .../validation/OMClientVersionValidator.java | 100 +++ .../validation/OMLayoutVersionValidator.java | 105 ++++ .../validation/RequestFeatureValidator.java | 1 + .../validation/RequestValidations.java | 4 +- .../request/validation/ValidatorRegistry.java | 5 +- .../request/validation/VersionExtractor.java | 13 +- .../OzoneManagerRequestHandler.java | 2 +- .../validation/TestOMValidatorProcessor.java | 583 ++++++++++++++++++ .../TestRequestFeatureValidatorProcessor.java | 524 ---------------- .../validation/TestValidatorRegistry.java | 4 +- .../validation/TestVersionExtractor.java | 18 +- .../GeneralValidatorsForTesting.java | 4 +- ...ValidatorsForOnlyOldClientValidations.java | 2 +- 38 files changed, 1076 insertions(+), 602 deletions(-) rename hadoop-hdds/annotations/src/main/java/org/apache/ozone/annotations/{RequestFeatureValidatorProcessor.java => OmRequestFeatureValidatorProcessor.java} (88%) create mode 100644 hadoop-hdds/annotations/src/main/java/org/apache/ozone/annotations/RegisterValidatorProcessor.java create mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/request/validation/RegisterValidator.java rename hadoop-ozone/{ozone-manager/src/main/java/org/apache/hadoop/ozone/om => common/src/main/java/org/apache/hadoop/ozone}/request/validation/RequestProcessingPhase.java (95%) create mode 100644 hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/request/validation/package-info.java create mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/OMClientVersionValidator.java create mode 100644 hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/OMLayoutVersionValidator.java create mode 100644 hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestOMValidatorProcessor.java delete mode 100644 hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestRequestFeatureValidatorProcessor.java diff --git a/hadoop-hdds/annotations/src/main/java/org/apache/ozone/annotations/RequestFeatureValidatorProcessor.java b/hadoop-hdds/annotations/src/main/java/org/apache/ozone/annotations/OmRequestFeatureValidatorProcessor.java similarity index 88% rename from hadoop-hdds/annotations/src/main/java/org/apache/ozone/annotations/RequestFeatureValidatorProcessor.java rename to hadoop-hdds/annotations/src/main/java/org/apache/ozone/annotations/OmRequestFeatureValidatorProcessor.java index 830706e9a54..0c93caba7e6 100644 --- a/hadoop-hdds/annotations/src/main/java/org/apache/ozone/annotations/RequestFeatureValidatorProcessor.java +++ b/hadoop-hdds/annotations/src/main/java/org/apache/ozone/annotations/OmRequestFeatureValidatorProcessor.java @@ -34,6 +34,7 @@ import javax.lang.model.type.TypeMirror; import javax.lang.model.util.SimpleAnnotationValueVisitor8; import javax.tools.Diagnostic; +import java.util.Arrays; import java.util.List; import java.util.Map.Entry; import java.util.Set; @@ -50,14 +51,11 @@ * META-INF/services/javax.annotation.processing.Processor file in the module's * resources folder. */ -@SupportedAnnotationTypes( - "org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator") +@SupportedAnnotationTypes({ + "org.apache.hadoop.ozone.om.request.validation.OMClientVersionValidator", + "org.apache.hadoop.ozone.om.request.validation.OMLayoutVersionValidator"}) @SupportedSourceVersion(SourceVersion.RELEASE_8) -public class RequestFeatureValidatorProcessor extends AbstractProcessor { - - public static final String ERROR_CONDITION_IS_EMPTY = - "RequestFeatureValidator has an empty condition list. Please define the" - + " ValidationCondition in which the validator has to be applied."; +public class OmRequestFeatureValidatorProcessor extends AbstractProcessor { public static final String ERROR_ANNOTATED_ELEMENT_IS_NOT_A_METHOD = "RequestFeatureValidator annotation is not applied to a method."; public static final String ERROR_VALIDATOR_METHOD_HAS_TO_BE_STATIC = @@ -90,8 +88,8 @@ public class RequestFeatureValidatorProcessor extends AbstractProcessor { public static final String VALIDATION_CONTEXT_CLASS_NAME = "org.apache.hadoop.ozone.om.request.validation.ValidationContext"; - public static final String ANNOTATION_SIMPLE_NAME = "RequestFeatureValidator"; - public static final String ANNOTATION_CONDITIONS_PROPERTY_NAME = "conditions"; + private static final List ANNOTATION_SIMPLE_NAMES = Arrays.asList("OMClientVersionValidator", + "OMLayoutVersionValidator"); public static final String ANNOTATION_PROCESSING_PHASE_PROPERTY_NAME = "processingPhase"; @@ -104,7 +102,7 @@ public class RequestFeatureValidatorProcessor extends AbstractProcessor { public boolean process(Set annotations, RoundEnvironment roundEnv) { for (TypeElement annotation : annotations) { - if (!annotation.getSimpleName().contentEquals(ANNOTATION_SIMPLE_NAME)) { + if (!ANNOTATION_SIMPLE_NAMES.contains(annotation.getSimpleName().toString())) { continue; } processElements(roundEnv.getElementsAnnotatedWith(annotation)); @@ -172,7 +170,7 @@ private void ensurePostProcessorReturnsOMResponse( ExecutableElement elem, boolean isPreprocessor) { if (!isPreprocessor && !elem.getReturnType().toString() .equals(OM_RESPONSE_CLASS_NAME)) { - emitErrorMsg(ERROR_VALIDATOR_METHOD_HAS_TO_RETURN_OMRESPONSE); + emitErrorMsg(ERROR_VALIDATOR_METHOD_HAS_TO_RETURN_OMRESPONSE + " " + elem.getSimpleName()); } } @@ -201,10 +199,6 @@ private boolean checkAndEvaluateAnnotation( boolean isPreprocessor = false; for (Entry entry : methodAnnotation.getElementValues().entrySet()) { - - if (hasInvalidValidationCondition(entry)) { - emitErrorMsg(ERROR_CONDITION_IS_EMPTY); - } if (isProcessingPhaseValue(entry)) { isPreprocessor = evaluateProcessingPhase(entry); } @@ -228,11 +222,6 @@ private boolean isProcessingPhaseValue( return isPropertyNamedAs(entry, ANNOTATION_PROCESSING_PHASE_PROPERTY_NAME); } - private boolean hasInvalidValidationCondition( - Entry entry) { - return isPropertyNamedAs(entry, ANNOTATION_CONDITIONS_PROPERTY_NAME) - && !visit(entry, new ConditionValidator()); - } private boolean isPropertyNamedAs( Entry entry, @@ -246,24 +235,6 @@ private T visit( return entry.getValue().accept(visitor, null); } - private static class ConditionValidator - extends SimpleAnnotationValueVisitor8 { - - ConditionValidator() { - super(Boolean.TRUE); - } - - @Override - public Boolean visitArray(List vals, - Void unused) { - if (vals.isEmpty()) { - return Boolean.FALSE; - } - return Boolean.TRUE; - } - - } - private static class ProcessingPhaseVisitor extends SimpleAnnotationValueVisitor8 { diff --git a/hadoop-hdds/annotations/src/main/java/org/apache/ozone/annotations/RegisterValidatorProcessor.java b/hadoop-hdds/annotations/src/main/java/org/apache/ozone/annotations/RegisterValidatorProcessor.java new file mode 100644 index 00000000000..8089c330e4a --- /dev/null +++ b/hadoop-hdds/annotations/src/main/java/org/apache/ozone/annotations/RegisterValidatorProcessor.java @@ -0,0 +1,142 @@ +/* + * 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 javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; +import javax.tools.Diagnostic; +import java.util.Set; + +/** + * This class is an annotation processor that is hooked into the java compiler + * and is used to validate the RegisterValidator annotations in the + * codebase, to ensure that the annotated classes have the proper methods returning appropriate object types. + * + * The module is compiled in a different execution via Maven before anything + * else is compiled, and then javac picks this class up as an annotation + * processor from the classpath via a ServiceLoader, based on the + * META-INF/services/javax.annotation.processing.Processor file in the module's + * resources folder. + */ +@SupportedAnnotationTypes("org.apache.hadoop.ozone.request.validation.RegisterValidator") +@SupportedSourceVersion(SourceVersion.RELEASE_8) +public class RegisterValidatorProcessor extends AbstractProcessor { + + public static final String ANNOTATION_SIMPLE_NAME = "RegisterValidator"; + public static final String VERSION_CLASS_NAME = "org.apache.hadoop.ozone.Version"; + public static final String REQUEST_PROCESSING_PHASE_CLASS_NAME = "org.apache.hadoop.ozone.om.request.validation" + + ".RequestProcessingPhase"; + public static final String APPLY_BEFORE_METHOD_NAME = "applyBefore"; + public static final String REQUEST_TYPE_METHOD_NAME = "requestType"; + public static final String PROCESSING_PHASE_METHOD_NAME = "processingPhase"; + + public static final String MAX_VERSION_NOT_FOUND_ERROR_MESSAGE = "Method " + APPLY_BEFORE_METHOD_NAME + + " returning an enum implementing " + VERSION_CLASS_NAME + " not found"; + public static final String REQUEST_TYPE_NOT_FOUND_ERROR_MESSAGE = "Method " + REQUEST_TYPE_METHOD_NAME + + " returning an enum not found"; + public static final String PROCESSING_PHASE_NOT_FOUND_ERROR_MESSAGE = "Method " + PROCESSING_PHASE_METHOD_NAME + + " returning an enum implementing " + REQUEST_PROCESSING_PHASE_CLASS_NAME + " not found"; + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + for (TypeElement annotation : annotations) { + if (!annotation.getSimpleName().contentEquals(ANNOTATION_SIMPLE_NAME)) { + continue; + } + processElements(roundEnv.getElementsAnnotatedWith(annotation)); + } + return false; + } + + private boolean validateArrayMethod(ExecutableElement method, String expectedMethodName, + ElementKind expectedReturnType, + String expectedReturnClass) { + Elements elementUtils = processingEnv.getElementUtils(); + Types types = processingEnv.getTypeUtils(); + TypeElement expectedReturnInterface = expectedReturnClass == null || expectedReturnClass.equals("") ? null : + elementUtils.getTypeElement(expectedReturnClass); + return method.getSimpleName().toString().equals(expectedMethodName) && (expectedReturnType == null || + TypeKind.ARRAY.equals(method.getReturnType().getKind()) && + types.asElement(((ArrayType)method.getReturnType()).getComponentType()).getKind() == expectedReturnType) && + (expectedReturnInterface == null || + types.isAssignable(types.asElement(method.getReturnType()).asType(), expectedReturnInterface.asType())); + } + + private boolean validateMethod(ExecutableElement method, String expectedMethodName, ElementKind expectedReturnType, + String expectedReturnClass) { + Elements elementUtils = processingEnv.getElementUtils(); + Types types = processingEnv.getTypeUtils(); + TypeElement expectedReturnInterface = expectedReturnClass == null || expectedReturnClass.equals("") ? null : + elementUtils.getTypeElement(expectedReturnClass); + return method.getSimpleName().toString().equals(expectedMethodName) && (expectedReturnType == null || + types.asElement(method.getReturnType()) != null && + types.asElement(method.getReturnType()).getKind() == expectedReturnType) && + (expectedReturnInterface == null || + types.isAssignable(types.asElement(method.getReturnType()).asType(), expectedReturnInterface.asType())); + } + + private void processElements(Set annotatedElements) { + for (Element element : annotatedElements) { + if (element.getKind().equals(ElementKind.ANNOTATION_TYPE)) { + boolean hasApplyBeforeMethod = false; + boolean hasRequestType = false; + boolean hasRequestProcessPhase = false; + for (Element enclosedElement : element.getEnclosedElements()) { + // Check if the annotation has a method called "validatorName" returning a String + if (enclosedElement instanceof ExecutableElement) { + ExecutableElement method = (ExecutableElement) enclosedElement; + hasApplyBeforeMethod = hasApplyBeforeMethod || validateMethod(method, APPLY_BEFORE_METHOD_NAME, + ElementKind.ENUM, VERSION_CLASS_NAME); + hasRequestType = hasRequestType || validateArrayMethod(method, REQUEST_TYPE_METHOD_NAME, ElementKind.ENUM, + null); + hasRequestProcessPhase = hasRequestProcessPhase || validateMethod(method, PROCESSING_PHASE_METHOD_NAME, + ElementKind.ENUM, REQUEST_PROCESSING_PHASE_CLASS_NAME); + } + } + if (!hasApplyBeforeMethod) { + emitErrorMsg(MAX_VERSION_NOT_FOUND_ERROR_MESSAGE + " for " + + element.getSimpleName().toString()); + } + if (!hasRequestType) { + emitErrorMsg(REQUEST_TYPE_NOT_FOUND_ERROR_MESSAGE + " for " + + element.getSimpleName().toString()); + } + if (!hasRequestProcessPhase) { + emitErrorMsg(PROCESSING_PHASE_NOT_FOUND_ERROR_MESSAGE + " for " + + element.getSimpleName().toString()); + } + } + } + } + + + private void emitErrorMsg(String s) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, s); + } +} diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/request/validation/RegisterValidator.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/request/validation/RegisterValidator.java new file mode 100644 index 00000000000..d2b3d7b3773 --- /dev/null +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/request/validation/RegisterValidator.java @@ -0,0 +1,41 @@ +/* + * 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.hadoop.ozone.request.validation; + +import org.apache.hadoop.ozone.Versioned; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +/** + * Annotations to register a validator. {@link org.apache.ozone.annotations.RegisterValidatorProcessor} + * enforces other annotation to have the following methods: + * applyBefore : Returns an enum which implement {@link Versioned} + * requestType: Returns an Enum value. + * processingPhase: Returns {@link RequestProcessingPhase} + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.ANNOTATION_TYPE) +public @interface RegisterValidator { + String APPLY_BEFORE_METHOD_NAME = "applyBefore"; + String REQUEST_TYPE_METHOD_NAME = "requestType"; + String PROCESSING_PHASE_METHOD_NAME = "processingPhase"; +} diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/RequestProcessingPhase.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/request/validation/RequestProcessingPhase.java similarity index 95% rename from hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/RequestProcessingPhase.java rename to hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/request/validation/RequestProcessingPhase.java index 67215684291..225ac1a6d45 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/RequestProcessingPhase.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/request/validation/RequestProcessingPhase.java @@ -14,7 +14,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package org.apache.hadoop.ozone.om.request.validation; +package org.apache.hadoop.ozone.request.validation; /** * Processing phase defines when a request validator should run. diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/request/validation/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/request/validation/package-info.java new file mode 100644 index 00000000000..2666db0b606 --- /dev/null +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/request/validation/package-info.java @@ -0,0 +1,40 @@ +/* + * 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. + */ +/** + * Request's validation handling. + * + * This package holds facilities to add new situation specific behaviour to + * request handling without cluttering the basic logic of the request handler + * code for any server. + * {@link org.apache.hadoop.ozone.request.validation.RegisterValidator} + * is used to register any validator which has the following methods: + * - applyBefore : Returns an enum which implement {@link org.apache.hadoop.ozone.Version} + * - requestType: Returns an Enum value. + * - processingPhase: Returns {@link org.apache.hadoop.ozone.request.validation.RequestProcessingPhase} + * + * The system uses a reflection based discovery to find methods that are + * annotated with the + * {@link org.apache.hadoop.ozone.request.validation.RegisterValidator} + * annotation. + * This annotation is used to register a particular annotation which inturn would be used to specify conditions in + * which a certain validator has to be used, the request type to which the validation should be applied, + * and the request processing phase in which we apply the validation and the maxVersion corresponding to which this + * is supposed to run. + */ + +package org.apache.hadoop.ozone.request.validation; diff --git a/hadoop-ozone/ozone-manager/pom.xml b/hadoop-ozone/ozone-manager/pom.xml index 8e78814eb6b..6eced24a067 100644 --- a/hadoop-ozone/ozone-manager/pom.xml +++ b/hadoop-ozone/ozone-manager/pom.xml @@ -419,7 +419,8 @@ https://maven.apache.org/xsd/maven-4.0.0.xsd"> org.apache.hadoop.hdds.conf.ConfigFileGenerator - org.apache.ozone.annotations.RequestFeatureValidatorProcessor + org.apache.ozone.annotations.OmRequestFeatureValidatorProcessor + org.apache.ozone.annotations.RegisterValidatorProcessor diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java index 3c21a2a851b..df22b6a70ae 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketCreateRequest.java @@ -43,7 +43,7 @@ import org.apache.hadoop.ozone.om.request.OMClientRequest; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.om.response.OMClientResponse; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketDeleteRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketDeleteRequest.java index 22e710dc911..6c582a8ff08 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketDeleteRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketDeleteRequest.java @@ -33,7 +33,7 @@ import org.apache.hadoop.ozone.om.helpers.SnapshotInfo; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.slf4j.Logger; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketSetPropertyRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketSetPropertyRequest.java index 941b41ca49b..c72007379c0 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketSetPropertyRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/bucket/OMBucketSetPropertyRequest.java @@ -34,7 +34,7 @@ import org.apache.hadoop.ozone.om.helpers.BucketEncryptionKeyInfo; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/file/OMDirectoryCreateRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/file/OMDirectoryCreateRequest.java index 732886fa0e6..43837fdfff5 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/file/OMDirectoryCreateRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/file/OMDirectoryCreateRequest.java @@ -32,7 +32,7 @@ import org.apache.hadoop.ozone.om.helpers.OmKeyInfo; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/file/OMFileCreateRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/file/OMFileCreateRequest.java index 08b25718288..d45df8a8f13 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/file/OMFileCreateRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/file/OMFileCreateRequest.java @@ -35,7 +35,7 @@ import org.apache.hadoop.ozone.om.helpers.BucketLayout; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.om.response.file.OMFileCreateResponse; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMAllocateBlockRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMAllocateBlockRequest.java index bbf5ec0afaf..6be695a23ac 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMAllocateBlockRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMAllocateBlockRequest.java @@ -32,7 +32,7 @@ import org.apache.hadoop.ozone.om.helpers.QuotaUtil; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCommitRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCommitRequest.java index 87d126de98a..224bb5a5028 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCommitRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCommitRequest.java @@ -42,7 +42,7 @@ import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.util.OmKeyHSyncUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCreateRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCreateRequest.java index e817901c22e..083c94beac6 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCreateRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCreateRequest.java @@ -37,7 +37,7 @@ import org.apache.hadoop.ozone.om.request.file.OMFileRequest; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequest.java index db1adc13893..3c6a0dd11e5 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyDeleteRequest.java @@ -31,7 +31,7 @@ import org.apache.hadoop.ozone.om.helpers.OmBucketInfo; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRenameRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRenameRequest.java index 35940f5a770..c06b33bb6cc 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRenameRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyRenameRequest.java @@ -28,7 +28,7 @@ import org.apache.hadoop.ozone.om.helpers.BucketLayout; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeysDeleteRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeysDeleteRequest.java index e090d61afd3..da4ee939938 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeysDeleteRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeysDeleteRequest.java @@ -39,7 +39,7 @@ import org.apache.hadoop.ozone.om.helpers.OzoneFileStatus; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.om.response.OMClientResponse; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeysRenameRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeysRenameRequest.java index 0d105c1d227..a45cb18ef6f 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeysRenameRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeysRenameRequest.java @@ -35,7 +35,7 @@ import org.apache.hadoop.ozone.om.helpers.OmKeyInfo; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.om.response.OMClientResponse; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeyAddAclRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeyAddAclRequest.java index 90a6dfa31ad..be66575b5f6 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeyAddAclRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeyAddAclRequest.java @@ -35,7 +35,7 @@ import org.apache.hadoop.ozone.om.request.util.ObjectParser; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.om.response.key.acl.OMKeyAclResponse; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeyRemoveAclRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeyRemoveAclRequest.java index 00af126e1e4..f5e45862e95 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeyRemoveAclRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeyRemoveAclRequest.java @@ -35,7 +35,7 @@ import org.apache.hadoop.ozone.om.request.util.ObjectParser; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.om.response.key.acl.OMKeyAclResponse; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeySetAclRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeySetAclRequest.java index 2f50fde5cb9..134f6fac317 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeySetAclRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/acl/OMKeySetAclRequest.java @@ -36,7 +36,7 @@ import org.apache.hadoop.ozone.om.request.util.ObjectParser; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.om.response.key.acl.OMKeyAclResponse; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3InitiateMultipartUploadRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3InitiateMultipartUploadRequest.java index 0a2703c769e..116bd3d6833 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3InitiateMultipartUploadRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3InitiateMultipartUploadRequest.java @@ -38,7 +38,7 @@ import org.apache.hadoop.ozone.om.request.util.OMMultipartUploadUtils; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.om.response.OMClientResponse; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadAbortRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadAbortRequest.java index 268c92dbd6e..028d3ca3756 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadAbortRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadAbortRequest.java @@ -30,7 +30,7 @@ import org.apache.hadoop.ozone.om.request.util.OMMultipartUploadUtils; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCommitPartRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCommitPartRequest.java index 16ab458a014..87c7dbb58ff 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCommitPartRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCommitPartRequest.java @@ -34,7 +34,7 @@ import org.apache.hadoop.ozone.om.request.key.OMKeyRequest; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.om.response.OMClientResponse; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCompleteRequest.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCompleteRequest.java index 2bb77005c95..00889504f8b 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCompleteRequest.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCompleteRequest.java @@ -55,7 +55,7 @@ import org.apache.hadoop.ozone.om.request.key.OMKeyRequest; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.om.response.OMClientResponse; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/OMClientVersionValidator.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/OMClientVersionValidator.java new file mode 100644 index 00000000000..6b57f2cd404 --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/OMClientVersionValidator.java @@ -0,0 +1,100 @@ +/* + * 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.hadoop.ozone.om.request.validation; + +import org.apache.hadoop.ozone.ClientVersion; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type; +import org.apache.hadoop.ozone.request.validation.RegisterValidator; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * An annotation to mark methods that do certain request validations based on the + * request protocol's client version. + * + * The methods annotated with this annotation are collected by the + * {@link ValidatorRegistry} class during the initialization of the server. + * + * The conditions specify the specific use case in which the validator should be + * applied to the request. See {@link VersionExtractor} for getting all the supported different + * {@link org.apache.hadoop.ozone.Versioned}. + * The validator method should be applied the specified request types + * to help keep these methods simple and straightforward. If you want to use + * the same validation for different requests just put it as part of the lists of request types. + * + * The annotated methods have to have a fixed signature. + * A {@link RequestProcessingPhase#PRE_PROCESS} phase method is running before + * the request is processed by the regular code. + * Its signature has to be the following: + * - it has to be static and idempotent + * - it has to have two parameters + * - the first parameter it is an + * {@link + * org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest} + * - the second parameter of type {@link ValidationContext} + * - the method has to return the modified request, or throw a ServiceException + * in case the request is considered to be invalid + * - the method does not need to care about preserving the request it gets, + * the original request is captured and saved by the calling environment. + * + * A {@link RequestProcessingPhase#POST_PROCESS} phase method is running once + * the + * {@link + * org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse} + * is calculated for a given request. + * Its signature has to be the following: + * - it has to be static and idempotent + * - it has three parameters + * - similarly to the pre-processing validators, first parameter is the + * OMRequest, the second parameter is the OMResponse, and the third + * parameter is a ValidationContext. + * - the method has to return the modified OMResponse or throw a + * ServiceException if the request is considered invalid based on response. + * - the method gets the request object that was supplied for the general + * request processing code, not the original request, while it gets a copy + * of the original response object provided by the general request processing + * code. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@RegisterValidator +public @interface OMClientVersionValidator { + + /** + * Defines if the validation has to run before or after the general request + * processing. + * @return if this is a pre or post processing validator + */ + RequestProcessingPhase processingPhase(); + + /** + * The type of the request handled by this validator method. + * @return the requestType to whihc the validator should be applied + */ + Type[] requestType(); + + /** + * The max version for which the validator would run. The validator would run for the request + * where the version is older than the excluding of the specified version. + * @returns the max client version until which the validator runs excluding the specified version itself. + */ + ClientVersion applyBefore(); + +} diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/OMLayoutVersionValidator.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/OMLayoutVersionValidator.java new file mode 100644 index 00000000000..9b7120d0f91 --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/OMLayoutVersionValidator.java @@ -0,0 +1,105 @@ +/* + * 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.hadoop.ozone.om.request.validation; + +import org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type; +import org.apache.hadoop.ozone.request.validation.RegisterValidator; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * An annotation to mark methods that do certain request validations based on the + * server's layout version and capability to perform a certain operation. + * + * The methods annotated with this annotation are collected by the + * {@link ValidatorRegistry} class during the initialization of the server. + * + * The conditions specify the specific use case in which the validator should be + * applied to the request. See {@link VersionExtractor} for getting all the supported different + * {@link org.apache.hadoop.ozone.Versioned}. + * The validator method should be applied to just one specific request type + * to help keep these methods simple and straightforward. If you want to use + * the same validation for different request types, use inheritance, and + * annotate the override method that just calls super. + * Note that the aim is to have these validators together with the request + * processing code, so the handling of these specific situations are easy to + * find. + * + * The annotated methods have to have a fixed signature. + * A {@link RequestProcessingPhase#PRE_PROCESS} phase method is running before + * the request is processed by the regular code. + * Its signature has to be the following: + * - it has to be static and idempotent + * - it has to have two parameters + * - the first parameter it is an + * {@link + * org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest} + * - the second parameter of type {@link ValidationContext} + * - the method has to return the modified request, or throw a ServiceException + * in case the request is considered to be invalid + * - the method does not need to care about preserving the request it gets, + * the original request is captured and saved by the calling environment. + * + * A {@link RequestProcessingPhase#POST_PROCESS} phase method is running once + * the + * {@link + * org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMResponse} + * is calculated for a given request. + * Its signature has to be the following: + * - it has to be static and idempotent + * - it has three parameters + * - similalry to the pre-processing validators, first parameter is the + * OMRequest, the second parameter is the OMResponse, and the third + * parameter is a ValidationContext. + * - the method has to return the modified OMResponse or throw a + * ServiceException if the request is considered invalid based on response. + * - the method gets the request object that was supplied for the general + * request processing code, not the original request, while it gets a copy + * of the original response object provided by the general request processing + * code. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@RegisterValidator +public @interface OMLayoutVersionValidator { + + /** + * Defines if the validation has to run before or after the general request + * processing. + * @return if this is a pre or post processing validator + */ + RequestProcessingPhase processingPhase(); + + /** + * The type of the request handled by this validator method. + * @return the requestType to whihc the validator should be applied + */ + Type[] requestType(); + + /** + * The max version for which the validator would run. The validator would run for the request + * where the version is older than the excluding of the specified version. + * @returns the max layout version until which the validator runs excluding the specified version itself. + */ + OMLayoutFeature applyBefore(); + +} diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/RequestFeatureValidator.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/RequestFeatureValidator.java index 5f1f08266b8..7cf724a38e6 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/RequestFeatureValidator.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/RequestFeatureValidator.java @@ -17,6 +17,7 @@ package org.apache.hadoop.ozone.om.request.validation; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/RequestValidations.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/RequestValidations.java index b9fbb0c927f..57d28f301e1 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/RequestValidations.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/RequestValidations.java @@ -29,8 +29,8 @@ import java.util.List; import java.util.stream.Collectors; -import static org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase.POST_PROCESS; -import static org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase.PRE_PROCESS; +import static org.apache.hadoop.ozone.request.validation.RequestProcessingPhase.POST_PROCESS; +import static org.apache.hadoop.ozone.request.validation.RequestProcessingPhase.PRE_PROCESS; /** * Main class to configure and set up and access the request/response diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/ValidatorRegistry.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/ValidatorRegistry.java index ac09664cc78..7c063c55cb4 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/ValidatorRegistry.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/ValidatorRegistry.java @@ -17,6 +17,7 @@ package org.apache.hadoop.ozone.om.request.validation; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.reflections.Reflections; import org.reflections.scanners.Scanners; import org.reflections.util.ClasspathHelper; @@ -34,8 +35,8 @@ import java.util.Set; import java.util.function.Supplier; -import static org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase.POST_PROCESS; -import static org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase.PRE_PROCESS; +import static org.apache.hadoop.ozone.request.validation.RequestProcessingPhase.POST_PROCESS; +import static org.apache.hadoop.ozone.request.validation.RequestProcessingPhase.PRE_PROCESS; /** * Registry that loads and stores the request validators to be applied by diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/VersionExtractor.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/VersionExtractor.java index e7acef45bfe..9c214d3122c 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/VersionExtractor.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/validation/VersionExtractor.java @@ -18,10 +18,11 @@ import org.apache.hadoop.ozone.ClientVersion; import org.apache.hadoop.ozone.Versioned; -import org.apache.hadoop.ozone.om.upgrade.OMLayoutFeature; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; import org.apache.hadoop.ozone.upgrade.LayoutVersionManager; +import java.lang.annotation.Annotation; + /** * Class to extract version out of OM request. */ @@ -37,8 +38,8 @@ public Versioned extractVersion(OMRequest req, ValidationContext ctx) { } @Override - public Class getVersionClass() { - return OMLayoutFeature.class; + public Class getValidatorClass() { + return OMLayoutVersionValidator.class; } }, @@ -53,11 +54,11 @@ public Versioned extractVersion(OMRequest req, ValidationContext ctx) { } @Override - public Class getVersionClass() { - return ClientVersion.class; + public Class getValidatorClass() { + return OMClientVersionValidator.class; } }; public abstract Versioned extractVersion(OMRequest req, ValidationContext ctx); - public abstract Class getVersionClass(); + public abstract Class getValidatorClass(); } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java index ab1f68d9928..0157be3b66f 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/protocolPB/OzoneManagerRequestHandler.java @@ -78,7 +78,7 @@ import org.apache.hadoop.ozone.om.request.OMClientRequest; import org.apache.hadoop.ozone.om.request.util.OmResponseUtil; import org.apache.hadoop.ozone.om.request.validation.RequestFeatureValidator; -import org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; import org.apache.hadoop.ozone.om.request.validation.ValidationCondition; import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.om.response.OMClientResponse; diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestOMValidatorProcessor.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestOMValidatorProcessor.java new file mode 100644 index 00000000000..2dd96e9d7d3 --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestOMValidatorProcessor.java @@ -0,0 +1,583 @@ +/* + * 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.hadoop.ozone.om.request.validation; + +import com.google.testing.compile.Compilation; +import com.google.testing.compile.JavaFileObjects; +import org.apache.hadoop.ozone.Versioned; +import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type; +import org.apache.hadoop.ozone.request.validation.RegisterValidator; +import org.apache.hadoop.ozone.request.validation.RequestProcessingPhase; +import org.apache.ozone.annotations.OmRequestFeatureValidatorProcessor; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.reflections.Reflections; +import org.reflections.scanners.Scanners; +import org.reflections.util.ClasspathHelper; +import org.reflections.util.ConfigurationBuilder; + +import java.lang.annotation.Annotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static com.google.testing.compile.CompilationSubject.assertThat; +import static com.google.testing.compile.Compiler.javac; +import static org.apache.ozone.annotations.OmRequestFeatureValidatorProcessor.ERROR_FIRST_PARAM_HAS_TO_BE_OMREQUEST; +import static org.apache.ozone.annotations.OmRequestFeatureValidatorProcessor.ERROR_LAST_PARAM_HAS_TO_BE_VALIDATION_CONTEXT; +import static org.apache.ozone.annotations.OmRequestFeatureValidatorProcessor.ERROR_SECOND_PARAM_HAS_TO_BE_OMRESPONSE; +import static org.apache.ozone.annotations.OmRequestFeatureValidatorProcessor.ERROR_UNEXPECTED_PARAMETER_COUNT; +import static org.apache.ozone.annotations.OmRequestFeatureValidatorProcessor.ERROR_VALIDATOR_METHOD_HAS_TO_BE_STATIC; +import static org.apache.ozone.annotations.OmRequestFeatureValidatorProcessor.ERROR_VALIDATOR_METHOD_HAS_TO_RETURN_OMREQUEST; +import static org.apache.ozone.annotations.OmRequestFeatureValidatorProcessor.ERROR_VALIDATOR_METHOD_HAS_TO_RETURN_OMRESPONSE; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; + +/** + * Compile tests against the annotation processor for all validators annotated with + * {@link RegisterValidator} annotation. + * + * The processor should ensure the method signatures and return values, based + * on annotation arguments provided. + */ +public class TestOMValidatorProcessor { + + private static final String CLASSNAME = "Validation"; + private static final Map, Class> ANNOTATION_VERSION_CLASS_MAP = new Reflections( + new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage("")).setScanners(Scanners.TypesAnnotated) + .setParallel(true)).getTypesAnnotatedWith(RegisterValidator.class).stream().filter(annotationClass -> { + try { + return annotationClass.getMethod(RegisterValidator.REQUEST_TYPE_METHOD_NAME).getReturnType() + .equals(Type[].class); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + }) + .collect(Collectors.toMap(Function.identity(), annotationClass -> { + try { + return annotationClass.getMethod(RegisterValidator.APPLY_BEFORE_METHOD_NAME).getReturnType(); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + })); + + private static Stream annotatedClasses() { + return ANNOTATION_VERSION_CLASS_MAP.entrySet().stream().flatMap(e -> + Arrays.stream(e.getValue().getEnumConstants()).map(version -> Arguments.of(e.getKey(), version))); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testAnnotationCanOnlyBeAppliedOnMethods(Class annotationClass, + V version) { + for (Annotation a : annotationClass.getAnnotations()) { + if (a instanceof Target) { + assertEquals(1, ((Target) a).value().length); + assertSame(((Target) a).value()[0], ElementType.METHOD); + } + } + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testACorrectAnnotationSetupForPreProcessCompiles(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(preProcess(), aReqType(), annotationClass, version), + modifiers("public", "static"), + returnValue("OMRequest"), + parameters("OMRequest rq", "ValidationContext ctx"), + exceptions("ServiceException"), annotationClass); + + assertThat(compile(source)).succeeded(); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testACorrectAnnotationSetupForPostProcessCompiles( + Class annotationClass, V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(postProcess(), aReqType(), annotationClass, version), + modifiers("public", "static"), + returnValue("OMResponse"), + parameters("OMRequest rq", "OMResponse rp", "ValidationContext ctx"), + exceptions("ServiceException"), annotationClass); + + assertThat(compile(source)).succeeded(); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testValidatorDoesNotNecessarilyThrowsExceptions(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(preProcess(), aReqType(), annotationClass, version), + modifiers("public", "static"), + returnValue("OMRequest"), + parameters("OMRequest rq", "ValidationContext ctx"), + exceptions(), annotationClass); + + assertThat(compile(source)).succeeded(); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testNonStaticValidatorDoesNotCompile(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(preProcess(), aReqType(), annotationClass, version), + modifiers("public"), + returnValue("OMRequest"), + parameters("OMRequest rq", "ValidationContext ctx"), + exceptions(), annotationClass); + + assertThat(compile(source)) + .hadErrorContaining(ERROR_VALIDATOR_METHOD_HAS_TO_BE_STATIC); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testValidatorMethodCanBeFinal(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(preProcess(), aReqType(), annotationClass, version), + modifiers("public", "static", "final"), + returnValue("OMRequest"), + parameters("OMRequest rq", "ValidationContext ctx"), + exceptions(), annotationClass); + + assertThat(compile(source)).succeeded(); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testValidatorMethodCanBePrivate(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(preProcess(), aReqType(), annotationClass, version), + modifiers("private", "static"), + returnValue("OMRequest"), + parameters("OMRequest rq", "ValidationContext ctx"), + exceptions(), annotationClass); + + assertThat(compile(source)).succeeded(); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testValidatorMethodCanBeDefaultVisible(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(preProcess(), aReqType(), annotationClass, version), + modifiers("static"), + returnValue("OMRequest"), + parameters("OMRequest rq", "ValidationContext ctx"), + exceptions(), annotationClass); + + assertThat(compile(source)).succeeded(); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testValidatorMethodCanBeProtected(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(preProcess(), aReqType(), annotationClass, version), + modifiers("protected", "static"), + returnValue("OMRequest"), + parameters("OMRequest rq", "ValidationContext ctx"), + exceptions(), annotationClass); + + assertThat(compile(source)).succeeded(); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testNotEnoughParametersForPreProcess(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(preProcess(), aReqType(), annotationClass, version), + modifiers("public", "static"), + returnValue("OMRequest"), + parameters("OMRequest rq"), + exceptions(), annotationClass); + + assertThat(compile(source)) + .hadErrorContaining( + String.format(ERROR_UNEXPECTED_PARAMETER_COUNT, 2, 1)); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testTooManyParametersForPreProcess(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(preProcess(), aReqType(), annotationClass, version), + modifiers("public", "static"), + returnValue("OMRequest"), + parameters("OMRequest rq", "OMResponse rp", "ValidationContext ctx"), + exceptions(), annotationClass); + + assertThat(compile(source)) + .hadErrorContaining( + String.format(ERROR_UNEXPECTED_PARAMETER_COUNT, 2, 3)); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testNotEnoughParametersForPostProcess(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(postProcess(), aReqType(), annotationClass, version), + modifiers("public", "static"), + returnValue("OMResponse"), + parameters("OMRequest rq", "OMResponse rp"), + exceptions(), annotationClass); + + assertThat(compile(source)) + .hadErrorContaining( + String.format(ERROR_UNEXPECTED_PARAMETER_COUNT, 3, 2)); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testTooManyParametersForPostProcess(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(postProcess(), aReqType(), annotationClass, version), + modifiers("public", "static"), + returnValue("OMResponse"), + parameters("OMRequest rq", "OMResponse rp", "ValidationContext ctx", + "String name"), + exceptions(), annotationClass); + + assertThat(compile(source)) + .hadErrorContaining( + String.format(ERROR_UNEXPECTED_PARAMETER_COUNT, 3, 4)); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testWrongReturnValueForPreProcess(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(preProcess(), aReqType(), annotationClass, version), + modifiers("public", "static"), + returnValue("String"), + parameters("OMRequest rq", "ValidationContext ctx"), + exceptions(), annotationClass); + + assertThat(compile(source)) + .hadErrorContaining(ERROR_VALIDATOR_METHOD_HAS_TO_RETURN_OMREQUEST); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testWrongReturnValueForPostProcess(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(postProcess(), aReqType(), annotationClass, version), + modifiers("public", "static"), + returnValue("String"), + parameters("OMRequest rq", "OMResponse rp", "ValidationContext ctx"), + exceptions(), annotationClass); + + assertThat(compile(source)) + .hadErrorContaining(ERROR_VALIDATOR_METHOD_HAS_TO_RETURN_OMRESPONSE); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testWrongFirstArgumentForPreProcess(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(preProcess(), aReqType(), annotationClass, version), + modifiers("public", "static"), + returnValue("OMRequest"), + parameters("String rq", "ValidationContext ctx"), + exceptions(), annotationClass); + + assertThat(compile(source)) + .hadErrorContaining(ERROR_FIRST_PARAM_HAS_TO_BE_OMREQUEST); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testWrongFirstArgumentForPostProcess(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(postProcess(), aReqType(), annotationClass, version), + modifiers("public", "static"), + returnValue("OMResponse"), + parameters("String rq", "OMResponse rp", "ValidationContext ctx"), + exceptions(), annotationClass); + + assertThat(compile(source)) + .hadErrorContaining(ERROR_FIRST_PARAM_HAS_TO_BE_OMREQUEST); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testWrongSecondArgumentForPreProcess(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(preProcess(), aReqType(), annotationClass, version), + modifiers("public", "static"), + returnValue("OMRequest"), + parameters("OMRequest rq", "String ctx"), + exceptions(), annotationClass); + + assertThat(compile(source)) + .hadErrorContaining(ERROR_LAST_PARAM_HAS_TO_BE_VALIDATION_CONTEXT); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testWrongSecondArgumentForPostProcess(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(postProcess(), aReqType(), annotationClass, version), + modifiers("public", "static"), + returnValue("OMResponse"), + parameters("OMRequest rq", "String rp", "ValidationContext ctx"), + exceptions(), annotationClass); + + assertThat(compile(source)) + .hadErrorContaining(ERROR_SECOND_PARAM_HAS_TO_BE_OMRESPONSE); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testWrongThirdArgumentForPostProcess(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(postProcess(), aReqType(), annotationClass, version), + modifiers("public", "static"), + returnValue("OMResponse"), + parameters("OMRequest rq", "OMResponse rp", "String ctx"), + exceptions(), annotationClass); + + assertThat(compile(source)) + .hadErrorContaining(ERROR_LAST_PARAM_HAS_TO_BE_VALIDATION_CONTEXT); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testInvalidProcessingPhase(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf("INVALID", aReqType(), annotationClass, version), + modifiers("public", "static"), + returnValue("OMResponse"), + parameters("OMRequest rq", "OMResponse rp", "ValidationContext ctx"), + exceptions("ServiceException"), annotationClass); + + assertThat(compile(source)).failed(); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testInvalidClientVersion(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(RequestProcessingPhase.PRE_PROCESS, aReqType(), annotationClass, null), + modifiers("public", "static"), + returnValue("OMResponse"), + parameters("OMRequest rq", "OMResponse rp", "ValidationContext ctx"), + exceptions("ServiceException"), annotationClass); + + assertThat(compile(source)).failed(); + } + + @ParameterizedTest + @MethodSource("annotatedClasses") + public & Versioned> void testMultipleErrorMessages(Class annotationClass, + V version) { + List source = generateSourceOfValidatorMethodWith( + annotationOf(postProcess(), aReqType(), annotationClass, version), + modifiers(), + returnValue("String"), + parameters("String rq", "int rp", "String ctx"), + exceptions(), annotationClass); + + Compilation compilation = compile(source); + assertThat(compilation) + .hadErrorContaining(ERROR_VALIDATOR_METHOD_HAS_TO_BE_STATIC); + assertThat(compilation) + .hadErrorContaining(ERROR_VALIDATOR_METHOD_HAS_TO_RETURN_OMRESPONSE); + assertThat(compilation) + .hadErrorContaining(ERROR_FIRST_PARAM_HAS_TO_BE_OMREQUEST); + assertThat(compilation) + .hadErrorContaining(ERROR_SECOND_PARAM_HAS_TO_BE_OMRESPONSE); + assertThat(compilation) + .hadErrorContaining(ERROR_LAST_PARAM_HAS_TO_BE_VALIDATION_CONTEXT); + } + + private Compilation compile(List source) { + Compilation c = javac() + .withProcessors(new OmRequestFeatureValidatorProcessor()) + .compile(JavaFileObjects.forSourceLines(CLASSNAME, source)); + c.diagnostics().forEach(System.out::println); + return c; + } + + private RequestProcessingPhase preProcess() { + return RequestProcessingPhase.PRE_PROCESS; + } + + private RequestProcessingPhase postProcess() { + return RequestProcessingPhase.POST_PROCESS; + } + + private Type aReqType() { + return Type.CreateVolume; + } + + private String returnValue(String retVal) { + return retVal; + } + + private String[] parameters(String... params) { + return params; + } + + private String[] modifiers(String... modifiers) { + return modifiers; + } + + private String[] exceptions(String... exceptions) { + return exceptions; + } + + private List generateSourceOfValidatorMethodWith( + String annotation, + String[] modifiers, + String returnType, + String[] paramspecs, + String[] exceptions, + Class annotationClass) { + List lines = new ArrayList<>(allImports(annotationClass)); + lines.add(""); + lines.add("public class " + CLASSNAME + " {"); + lines.add(""); + lines.add(" " + annotation); + StringBuilder signature = + buildMethodSignature(modifiers, returnType, paramspecs, exceptions); + lines.add(signature.toString()); + lines.add(" return null;"); + lines.add(" }"); + lines.add("}"); + lines.add(""); + lines.stream().forEach(System.out::println); + return lines; + } + + private & Versioned> String annotationOf( + RequestProcessingPhase phase, Type reqType, Class annotationClass, V applyBeforeVersion) { + return annotationOf(phase.name(), reqType, annotationClass, applyBeforeVersion); + } + + private & Versioned> String annotationOf( + String phase, + Type reqType, + Class annotationClass, + V applyBeforeVersion) { + StringBuilder annotation = new StringBuilder(); + annotation.append("@" + annotationClass.getName() + "("); + annotation.append("processingPhase = ").append(phase); + annotation.append(", requestType = ").append(reqType.name()); + if (applyBeforeVersion != null) { + annotation.append(", applyBefore = ").append(applyBeforeVersion.name()); + } + annotation.append(" )"); + return annotation.toString(); + } + + private List allImports(Class annotationClass) { + List imports = new ArrayList<>(); + imports.add("import org.apache.hadoop.ozone.protocol.proto" + + ".OzoneManagerProtocolProtos.OMRequest;"); + imports.add("import org.apache.hadoop.ozone.protocol.proto" + + ".OzoneManagerProtocolProtos.OMResponse;"); + imports.add("import org.apache.hadoop.ozone.om.request.validation" + + ".ValidationContext;"); + imports.add("import com.google.protobuf.ServiceException;"); + for (RequestProcessingPhase phase : RequestProcessingPhase.values()) { + imports.add("import static org.apache.hadoop.ozone.request.validation" + + ".RequestProcessingPhase." + phase.name() + ";"); + } + for (Type reqType : Type.values()) { + imports.add("import static org.apache.hadoop.ozone.protocol.proto" + + ".OzoneManagerProtocolProtos.Type." + reqType.name() + ";"); + } + imports.add("import " + annotationClass.getName() + ";"); + + for (Object enumConstant : ANNOTATION_VERSION_CLASS_MAP.get(annotationClass).getEnumConstants()) { + imports.add("import static " + ANNOTATION_VERSION_CLASS_MAP.get(annotationClass).getCanonicalName() + "." + + ((Enum)enumConstant).name() + ";"); + } + return imports; + } + + private StringBuilder buildMethodSignature( + String[] modifiers, String returnType, + String[] paramspecs, String[] exceptions) { + StringBuilder signature = new StringBuilder(); + signature.append(" "); + for (String modifier : modifiers) { + signature.append(modifier).append(" "); + } + signature.append(returnType).append(" "); + signature.append("validatorMethod("); + signature.append(createParameterList(paramspecs)); + signature.append(") "); + signature.append(createThrowsClause(exceptions)); + return signature.append(" {"); + } + + private String createParameterList(String[] paramSpecs) { + if (paramSpecs == null || paramSpecs.length == 0) { + return ""; + } + StringBuilder parameters = new StringBuilder(); + for (String paramSpec : paramSpecs) { + parameters.append(paramSpec).append(", "); + } + return parameters.substring(0, parameters.length() - 2); + } + + private String createThrowsClause(String[] exceptions) { + StringBuilder throwsClause = new StringBuilder(); + if (exceptions != null && exceptions.length > 0) { + throwsClause.append(" throws "); + StringBuilder exceptionList = new StringBuilder(); + for (String exception : exceptions) { + exceptionList.append(exception).append(", "); + } + throwsClause + .append(exceptionList.substring(0, exceptionList.length() - 2)); + } + return throwsClause.toString(); + } +} diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestRequestFeatureValidatorProcessor.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestRequestFeatureValidatorProcessor.java deleted file mode 100644 index 48947518abd..00000000000 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestRequestFeatureValidatorProcessor.java +++ /dev/null @@ -1,524 +0,0 @@ -/* - * 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.hadoop.ozone.om.request.validation; - -import com.google.testing.compile.Compilation; -import com.google.testing.compile.JavaFileObjects; -import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type; -import org.apache.ozone.annotations.RequestFeatureValidatorProcessor; -import org.junit.jupiter.api.Test; - -import java.lang.annotation.Annotation; -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; -import java.util.ArrayList; -import java.util.List; - -import static com.google.testing.compile.CompilationSubject.assertThat; -import static com.google.testing.compile.Compiler.javac; -import static org.apache.ozone.annotations.RequestFeatureValidatorProcessor.ERROR_CONDITION_IS_EMPTY; -import static org.apache.ozone.annotations.RequestFeatureValidatorProcessor.ERROR_FIRST_PARAM_HAS_TO_BE_OMREQUEST; -import static org.apache.ozone.annotations.RequestFeatureValidatorProcessor.ERROR_LAST_PARAM_HAS_TO_BE_VALIDATION_CONTEXT; -import static org.apache.ozone.annotations.RequestFeatureValidatorProcessor.ERROR_SECOND_PARAM_HAS_TO_BE_OMRESPONSE; -import static org.apache.ozone.annotations.RequestFeatureValidatorProcessor.ERROR_UNEXPECTED_PARAMETER_COUNT; -import static org.apache.ozone.annotations.RequestFeatureValidatorProcessor.ERROR_VALIDATOR_METHOD_HAS_TO_BE_STATIC; -import static org.apache.ozone.annotations.RequestFeatureValidatorProcessor.ERROR_VALIDATOR_METHOD_HAS_TO_RETURN_OMREQUEST; -import static org.apache.ozone.annotations.RequestFeatureValidatorProcessor.ERROR_VALIDATOR_METHOD_HAS_TO_RETURN_OMRESPONSE; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertSame; - -/** - * Compile tests against the annotation processor for the - * {@link RequestFeatureValidator} annotation. - * - * The processor should ensure the method signatures and return values, based - * on annotation arguments provided. - */ -public class TestRequestFeatureValidatorProcessor { - - private static final String CLASSNAME = "Validation"; - - @Test - public void testAnnotationCanOnlyBeAppliedOnMethods() { - Class c = RequestFeatureValidator.class; - for (Annotation a : c.getAnnotations()) { - if (a instanceof Target) { - assertEquals(1, ((Target) a).value().length); - assertSame(((Target) a).value()[0], ElementType.METHOD); - } - } - } - - @Test - public void testACorrectAnnotationSetupForPreProcessCompiles() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), preProcess(), aReqType()), - modifiers("public", "static"), - returnValue("OMRequest"), - parameters("OMRequest rq", "ValidationContext ctx"), - exceptions("ServiceException")); - - assertThat(compile(source)).succeeded(); - } - - @Test - public void testACorrectAnnotationSetupForPostProcessCompiles() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), postProcess(), aReqType()), - modifiers("public", "static"), - returnValue("OMResponse"), - parameters("OMRequest rq", "OMResponse rp", "ValidationContext ctx"), - exceptions("ServiceException")); - - assertThat(compile(source)).succeeded(); - } - - @Test - public void testValidatorDoesNotNecessarilyThrowsExceptions() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), preProcess(), aReqType()), - modifiers("public", "static"), - returnValue("OMRequest"), - parameters("OMRequest rq", "ValidationContext ctx"), - exceptions()); - - assertThat(compile(source)).succeeded(); - } - - @Test - public void testNonStaticValidatorDoesNotCompile() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), preProcess(), aReqType()), - modifiers("public"), - returnValue("OMRequest"), - parameters("OMRequest rq", "ValidationContext ctx"), - exceptions()); - - assertThat(compile(source)) - .hadErrorContaining(ERROR_VALIDATOR_METHOD_HAS_TO_BE_STATIC); - } - - @Test - public void testValidatorMethodCanBeFinal() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), preProcess(), aReqType()), - modifiers("public", "static", "final"), - returnValue("OMRequest"), - parameters("OMRequest rq", "ValidationContext ctx"), - exceptions()); - - assertThat(compile(source)).succeeded(); - } - - @Test - public void testValidatorMethodCanBePrivate() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), preProcess(), aReqType()), - modifiers("private", "static"), - returnValue("OMRequest"), - parameters("OMRequest rq", "ValidationContext ctx"), - exceptions()); - - assertThat(compile(source)).succeeded(); - } - - @Test - public void testValidatorMethodCanBeDefaultVisible() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), preProcess(), aReqType()), - modifiers("static"), - returnValue("OMRequest"), - parameters("OMRequest rq", "ValidationContext ctx"), - exceptions()); - - assertThat(compile(source)).succeeded(); - } - - @Test - public void testValidatorMethodCanBeProtected() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), preProcess(), aReqType()), - modifiers("protected", "static"), - returnValue("OMRequest"), - parameters("OMRequest rq", "ValidationContext ctx"), - exceptions()); - - assertThat(compile(source)).succeeded(); - } - - @Test - public void testEmptyValidationConditionListDoesNotCompile() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(emptyConditions(), preProcess(), aReqType()), - modifiers("public", "static"), - returnValue("OMRequest"), - parameters("OMRequest rq", "ValidationContext ctx"), - exceptions()); - - assertThat(compile(source)).hadErrorContaining(ERROR_CONDITION_IS_EMPTY); - } - - @Test - public void testNotEnoughParametersForPreProcess() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), preProcess(), aReqType()), - modifiers("public", "static"), - returnValue("OMRequest"), - parameters("OMRequest rq"), - exceptions()); - - assertThat(compile(source)) - .hadErrorContaining( - String.format(ERROR_UNEXPECTED_PARAMETER_COUNT, 2, 1)); - } - - @Test - public void testTooManyParametersForPreProcess() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), preProcess(), aReqType()), - modifiers("public", "static"), - returnValue("OMRequest"), - parameters("OMRequest rq", "OMResponse rp", "ValidationContext ctx"), - exceptions()); - - assertThat(compile(source)) - .hadErrorContaining( - String.format(ERROR_UNEXPECTED_PARAMETER_COUNT, 2, 3)); - } - - @Test - public void testNotEnoughParametersForPostProcess() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), postProcess(), aReqType()), - modifiers("public", "static"), - returnValue("OMResponse"), - parameters("OMRequest rq", "OMResponse rp"), - exceptions()); - - assertThat(compile(source)) - .hadErrorContaining( - String.format(ERROR_UNEXPECTED_PARAMETER_COUNT, 3, 2)); - } - - @Test - public void testTooManyParametersForPostProcess() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), postProcess(), aReqType()), - modifiers("public", "static"), - returnValue("OMResponse"), - parameters("OMRequest rq", "OMResponse rp", "ValidationContext ctx", - "String name"), - exceptions()); - - assertThat(compile(source)) - .hadErrorContaining( - String.format(ERROR_UNEXPECTED_PARAMETER_COUNT, 3, 4)); - } - - @Test - public void testWrongReturnValueForPreProcess() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), preProcess(), aReqType()), - modifiers("public", "static"), - returnValue("String"), - parameters("OMRequest rq", "ValidationContext ctx"), - exceptions()); - - assertThat(compile(source)) - .hadErrorContaining(ERROR_VALIDATOR_METHOD_HAS_TO_RETURN_OMREQUEST); - } - - @Test - public void testWrongReturnValueForPostProcess() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), postProcess(), aReqType()), - modifiers("public", "static"), - returnValue("String"), - parameters("OMRequest rq", "OMResponse rp", "ValidationContext ctx"), - exceptions()); - - assertThat(compile(source)) - .hadErrorContaining(ERROR_VALIDATOR_METHOD_HAS_TO_RETURN_OMRESPONSE); - } - - @Test - public void testWrongFirstArgumentForPreProcess() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), preProcess(), aReqType()), - modifiers("public", "static"), - returnValue("OMRequest"), - parameters("String rq", "ValidationContext ctx"), - exceptions()); - - assertThat(compile(source)) - .hadErrorContaining(ERROR_FIRST_PARAM_HAS_TO_BE_OMREQUEST); - } - - @Test - public void testWrongFirstArgumentForPostProcess() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), postProcess(), aReqType()), - modifiers("public", "static"), - returnValue("OMResponse"), - parameters("String rq", "OMResponse rp", "ValidationContext ctx"), - exceptions()); - - assertThat(compile(source)) - .hadErrorContaining(ERROR_FIRST_PARAM_HAS_TO_BE_OMREQUEST); - } - - @Test - public void testWrongSecondArgumentForPreProcess() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), preProcess(), aReqType()), - modifiers("public", "static"), - returnValue("OMRequest"), - parameters("OMRequest rq", "String ctx"), - exceptions()); - - assertThat(compile(source)) - .hadErrorContaining(ERROR_LAST_PARAM_HAS_TO_BE_VALIDATION_CONTEXT); - } - - @Test - public void testWrongSecondArgumentForPostProcess() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), postProcess(), aReqType()), - modifiers("public", "static"), - returnValue("OMResponse"), - parameters("OMRequest rq", "String rp", "ValidationContext ctx"), - exceptions()); - - assertThat(compile(source)) - .hadErrorContaining(ERROR_SECOND_PARAM_HAS_TO_BE_OMRESPONSE); - } - - @Test - public void testWrongThirdArgumentForPostProcess() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), postProcess(), aReqType()), - modifiers("public", "static"), - returnValue("OMResponse"), - parameters("OMRequest rq", "OMResponse rp", "String ctx"), - exceptions()); - - assertThat(compile(source)) - .hadErrorContaining(ERROR_LAST_PARAM_HAS_TO_BE_VALIDATION_CONTEXT); - } - - @Test - public void testInvalidProcessingPhase() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(someConditions(), "INVALID", aReqType()), - modifiers("public", "static"), - returnValue("OMResponse"), - parameters("OMRequest rq", "OMResponse rp", "ValidationContext ctx"), - exceptions("ServiceException")); - - assertThat(compile(source)).failed(); - } - - @Test - public void testMultipleErrorMessages() { - List source = generateSourceOfValidatorMethodWith( - annotationOf(emptyConditions(), postProcess(), aReqType()), - modifiers(), - returnValue("String"), - parameters("String rq", "int rp", "String ctx"), - exceptions()); - - Compilation compilation = compile(source); - assertThat(compilation).hadErrorContaining(ERROR_CONDITION_IS_EMPTY); - assertThat(compilation) - .hadErrorContaining(ERROR_VALIDATOR_METHOD_HAS_TO_BE_STATIC); - assertThat(compilation) - .hadErrorContaining(ERROR_VALIDATOR_METHOD_HAS_TO_RETURN_OMRESPONSE); - assertThat(compilation) - .hadErrorContaining(ERROR_FIRST_PARAM_HAS_TO_BE_OMREQUEST); - assertThat(compilation) - .hadErrorContaining(ERROR_SECOND_PARAM_HAS_TO_BE_OMRESPONSE); - assertThat(compilation) - .hadErrorContaining(ERROR_LAST_PARAM_HAS_TO_BE_VALIDATION_CONTEXT); - } - - private Compilation compile(List source) { - Compilation c = javac() - .withProcessors(new RequestFeatureValidatorProcessor()) - .compile(JavaFileObjects.forSourceLines(CLASSNAME, source)); - c.diagnostics().forEach(System.out::println); - return c; - } - - private ValidationCondition[] someConditions() { - return - new ValidationCondition[] {ValidationCondition.OLDER_CLIENT_REQUESTS}; - } - - private ValidationCondition[] emptyConditions() { - return new ValidationCondition[] {}; - } - - private RequestProcessingPhase preProcess() { - return RequestProcessingPhase.PRE_PROCESS; - } - - private RequestProcessingPhase postProcess() { - return RequestProcessingPhase.POST_PROCESS; - } - - private Type aReqType() { - return Type.CreateVolume; - } - - private String returnValue(String retVal) { - return retVal; - } - - private String[] parameters(String... params) { - return params; - } - - private String[] modifiers(String... modifiers) { - return modifiers; - } - - private String[] exceptions(String... exceptions) { - return exceptions; - } - - private List generateSourceOfValidatorMethodWith( - String annotation, - String[] modifiers, - String returnType, - String[] paramspecs, - String[] exceptions) { - List lines = new ArrayList<>(allImports()); - lines.add(""); - lines.add("public class " + CLASSNAME + " {"); - lines.add(""); - lines.add(" " + annotation); - StringBuilder signature = - buildMethodSignature(modifiers, returnType, paramspecs, exceptions); - lines.add(signature.toString()); - lines.add(" return null;"); - lines.add(" }"); - lines.add("}"); - lines.add(""); - lines.stream() - .filter(s -> !s.startsWith("import")) - .forEach(System.out::println); - return lines; - } - - private String annotationOf( - ValidationCondition[] conditions, - RequestProcessingPhase phase, - Type reqType) { - return annotationOf(conditions, phase.name(), reqType); - } - - private String annotationOf( - ValidationCondition[] conditions, - String phase, - Type reqType) { - StringBuilder annotation = new StringBuilder(); - annotation.append("@RequestFeatureValidator("); - StringBuilder conditionsArray = new StringBuilder(); - conditionsArray.append("conditions = { "); - if (conditions.length > 0) { - for (ValidationCondition condition : conditions) { - conditionsArray.append(condition.name()).append(", "); - } - annotation - .append(conditionsArray.substring(0, conditionsArray.length() - 2)); - } else { - annotation.append(conditionsArray); - } - annotation.append(" }"); - annotation.append(", processingPhase = ").append(phase); - annotation.append(", requestType = ").append(reqType.name()); - annotation.append(" )"); - return annotation.toString(); - } - - private List allImports() { - List imports = new ArrayList<>(); - imports.add("import org.apache.hadoop.ozone.om.request.validation" - + ".RequestFeatureValidator;"); - imports.add("import org.apache.hadoop.ozone.protocol.proto" - + ".OzoneManagerProtocolProtos.OMRequest;"); - imports.add("import org.apache.hadoop.ozone.protocol.proto" - + ".OzoneManagerProtocolProtos.OMResponse;"); - imports.add("import org.apache.hadoop.ozone.om.request.validation" - + ".ValidationContext;"); - imports.add("import com.google.protobuf.ServiceException;"); - for (ValidationCondition condition : ValidationCondition.values()) { - imports.add("import static org.apache.hadoop.ozone.om.request.validation" - + ".ValidationCondition." + condition.name() + ";"); - } - for (RequestProcessingPhase phase : RequestProcessingPhase.values()) { - imports.add("import static org.apache.hadoop.ozone.om.request.validation" - + ".RequestProcessingPhase." + phase.name() + ";"); - } - for (Type reqType : Type.values()) { - imports.add("import static org.apache.hadoop.ozone.protocol.proto" - + ".OzoneManagerProtocolProtos.Type." + reqType.name() + ";"); - } - return imports; - } - - private StringBuilder buildMethodSignature( - String[] modifiers, String returnType, - String[] paramspecs, String[] exceptions) { - StringBuilder signature = new StringBuilder(); - signature.append(" "); - for (String modifier : modifiers) { - signature.append(modifier).append(" "); - } - signature.append(returnType).append(" "); - signature.append("validatorMethod("); - signature.append(createParameterList(paramspecs)); - signature.append(") "); - signature.append(createThrowsClause(exceptions)); - return signature.append(" {"); - } - - private String createParameterList(String[] paramSpecs) { - if (paramSpecs == null || paramSpecs.length == 0) { - return ""; - } - StringBuilder parameters = new StringBuilder(); - for (String paramSpec : paramSpecs) { - parameters.append(paramSpec).append(", "); - } - return parameters.substring(0, parameters.length() - 2); - } - - private String createThrowsClause(String[] exceptions) { - StringBuilder throwsClause = new StringBuilder(); - if (exceptions != null && exceptions.length > 0) { - throwsClause.append(" throws "); - StringBuilder exceptionList = new StringBuilder(); - for (String exception : exceptions) { - exceptionList.append(exception).append(", "); - } - throwsClause - .append(exceptionList.substring(0, exceptionList.length() - 2)); - } - return throwsClause.toString(); - } -} diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestValidatorRegistry.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestValidatorRegistry.java index 076ba018727..0faead03b7f 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestValidatorRegistry.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestValidatorRegistry.java @@ -31,8 +31,8 @@ import static java.util.Arrays.asList; import static java.util.Collections.emptyList; -import static org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase.POST_PROCESS; -import static org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase.PRE_PROCESS; +import static org.apache.hadoop.ozone.request.validation.RequestProcessingPhase.POST_PROCESS; +import static org.apache.hadoop.ozone.request.validation.RequestProcessingPhase.PRE_PROCESS; import static org.apache.hadoop.ozone.om.request.validation.ValidationCondition.CLUSTER_NEEDS_FINALIZATION; import static org.apache.hadoop.ozone.om.request.validation.ValidationCondition.OLDER_CLIENT_REQUESTS; import static org.apache.hadoop.ozone.om.request.validation.testvalidatorset1.GeneralValidatorsForTesting.startValidatorTest; diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestVersionExtractor.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestVersionExtractor.java index a3c9c76e70f..5b3c0660a7c 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestVersionExtractor.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/TestVersionExtractor.java @@ -16,6 +16,7 @@ */ package org.apache.hadoop.ozone.om.request.validation; +import com.google.common.collect.ImmutableMap; import org.apache.hadoop.ozone.ClientVersion; import org.apache.hadoop.ozone.Versioned; import org.apache.hadoop.ozone.om.exceptions.OMException; @@ -23,10 +24,14 @@ import org.apache.hadoop.ozone.om.upgrade.OMLayoutVersionManager; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; import org.apache.hadoop.ozone.upgrade.LayoutVersionManager; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.ValueSource; +import java.lang.annotation.Annotation; +import java.util.Map; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -41,7 +46,6 @@ void testLayoutVersionExtractor(OMLayoutFeature layoutVersionValue) throws OMExc when(context.versionManager()).thenReturn(layoutVersionManager); Versioned version = VersionExtractor.LAYOUT_VERSION_EXTRACTOR.extractVersion(null, context); assertEquals(layoutVersionValue, version); - assertEquals(OMLayoutFeature.class, VersionExtractor.LAYOUT_VERSION_EXTRACTOR.getVersionClass()); } @ParameterizedTest @@ -51,7 +55,6 @@ void testClientVersionExtractor(ClientVersion expectedClientVersion) { when(request.getVersion()).thenReturn(expectedClientVersion.version()); Versioned version = VersionExtractor.CLIENT_VERSION_EXTRACTOR.extractVersion(request, null); assertEquals(expectedClientVersion, version); - assertEquals(ClientVersion.class, VersionExtractor.CLIENT_VERSION_EXTRACTOR.getVersionClass()); } @ParameterizedTest @@ -61,6 +64,15 @@ void testClientVersionExtractorForFutureValues(int futureVersion) { when(request.getVersion()).thenReturn(ClientVersion.CURRENT_VERSION + futureVersion); Versioned version = VersionExtractor.CLIENT_VERSION_EXTRACTOR.extractVersion(request, null); assertEquals(ClientVersion.FUTURE_VERSION, version); - assertEquals(ClientVersion.class, VersionExtractor.CLIENT_VERSION_EXTRACTOR.getVersionClass()); + } + + @Test + void testGetValidatorClass() { + Map> expectedValidatorClasses = + ImmutableMap.of(VersionExtractor.CLIENT_VERSION_EXTRACTOR, OMClientVersionValidator.class, + VersionExtractor.LAYOUT_VERSION_EXTRACTOR, OMLayoutVersionValidator.class); + for (VersionExtractor extractor : VersionExtractor.values()) { + assertEquals(expectedValidatorClasses.get(extractor), extractor.getValidatorClass()); + } } } diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/testvalidatorset1/GeneralValidatorsForTesting.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/testvalidatorset1/GeneralValidatorsForTesting.java index 35c3afa4cf9..e56b7725f42 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/testvalidatorset1/GeneralValidatorsForTesting.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/testvalidatorset1/GeneralValidatorsForTesting.java @@ -26,8 +26,8 @@ import java.util.ArrayList; import java.util.List; -import static org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase.POST_PROCESS; -import static org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase.PRE_PROCESS; +import static org.apache.hadoop.ozone.request.validation.RequestProcessingPhase.POST_PROCESS; +import static org.apache.hadoop.ozone.request.validation.RequestProcessingPhase.PRE_PROCESS; import static org.apache.hadoop.ozone.om.request.validation.ValidationCondition.CLUSTER_NEEDS_FINALIZATION; import static org.apache.hadoop.ozone.om.request.validation.ValidationCondition.OLDER_CLIENT_REQUESTS; import static org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type.CreateKey; diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/testvalidatorset2/ValidatorsForOnlyOldClientValidations.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/testvalidatorset2/ValidatorsForOnlyOldClientValidations.java index 447b9ab0260..b6faae53d6f 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/testvalidatorset2/ValidatorsForOnlyOldClientValidations.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/request/validation/testvalidatorset2/ValidatorsForOnlyOldClientValidations.java @@ -20,7 +20,7 @@ import org.apache.hadoop.ozone.om.request.validation.ValidationContext; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OMRequest; -import static org.apache.hadoop.ozone.om.request.validation.RequestProcessingPhase.PRE_PROCESS; +import static org.apache.hadoop.ozone.request.validation.RequestProcessingPhase.PRE_PROCESS; import static org.apache.hadoop.ozone.om.request.validation.ValidationCondition.OLDER_CLIENT_REQUESTS; import static org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.Type.CreateKey; From 35c84f7457efd3ffbca6d31c9ee3a14c97ebddf5 Mon Sep 17 00:00:00 2001 From: Swaminathan Balachandran Date: Mon, 30 Dec 2024 15:18:25 -0800 Subject: [PATCH 2/2] HDDS-11981. Fix javadoc Change-Id: I3650d42f70bb367d7060d69fee395752224d2970 --- .../apache/hadoop/ozone/request/validation/package-info.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/request/validation/package-info.java b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/request/validation/package-info.java index 2666db0b606..ab3adca607a 100644 --- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/request/validation/package-info.java +++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/request/validation/package-info.java @@ -23,7 +23,7 @@ * code for any server. * {@link org.apache.hadoop.ozone.request.validation.RegisterValidator} * is used to register any validator which has the following methods: - * - applyBefore : Returns an enum which implement {@link org.apache.hadoop.ozone.Version} + * - applyBefore : Returns an enum which implement {@link org.apache.hadoop.ozone.Versioned} * - requestType: Returns an Enum value. * - processingPhase: Returns {@link org.apache.hadoop.ozone.request.validation.RequestProcessingPhase} *