This is an automated email from the ASF dual-hosted git repository.
dblevins pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomee.git
The following commit(s) were added to refs/heads/main by this push:
new 81bf08aced Clean dead code and begin TOMEE-4043 Remove support for
JWTAuthConfiguration API
81bf08aced is described below
commit 81bf08aced1a83440d68012c7711952d49da4f33
Author: David Blevins <[email protected]>
AuthorDate: Mon Sep 12 18:49:57 2022 -0700
Clean dead code and begin TOMEE-4043 Remove support for
JWTAuthConfiguration API
---
.../microprofile/jwt/JsonWebTokenValidator.java | 175 ---------------
.../jwt/config/JWTAuthConfiguration.java | 54 +----
.../jwt/JsonWebTokenValidatorTest.java | 49 -----
.../jwt/bval/ValidationConstraintsTest.java | 244 ---------------------
4 files changed, 1 insertion(+), 521 deletions(-)
diff --git
a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/JsonWebTokenValidator.java
b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/JsonWebTokenValidator.java
deleted file mode 100644
index 2178832bc2..0000000000
---
a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/JsonWebTokenValidator.java
+++ /dev/null
@@ -1,175 +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.tomee.microprofile.jwt;
-
-import org.apache.openejb.util.Logger;
-import org.apache.tomee.microprofile.jwt.config.JWTAuthConfiguration;
-import org.apache.tomee.microprofile.jwt.config.KeyResolver;
-import org.apache.tomee.microprofile.jwt.principal.JWTCallerPrincipal;
-import org.eclipse.microprofile.jwt.Claims;
-import org.eclipse.microprofile.jwt.JsonWebToken;
-import org.jose4j.jwa.AlgorithmConstraints;
-import org.jose4j.jwk.JsonWebKey;
-import org.jose4j.jws.AlgorithmIdentifiers;
-import org.jose4j.jwt.JwtClaims;
-import org.jose4j.jwt.MalformedClaimException;
-import org.jose4j.jwt.NumericDate;
-import org.jose4j.jwt.consumer.InvalidJwtException;
-import org.jose4j.jwt.consumer.JwtConsumer;
-import org.jose4j.jwt.consumer.JwtConsumerBuilder;
-import org.jose4j.jwt.consumer.JwtContext;
-import org.jose4j.keys.resolvers.JwksVerificationKeyResolver;
-
-import java.security.Key;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Predicate;
-
-public class JsonWebTokenValidator {
-
- private static final Logger VALIDATION =
Logger.getInstance(JWTLogCategories.CONSTRAINT, JsonWebTokenValidator.class);
-
- private final Predicate<JsonWebToken> validation;
- private final Key verificationKey;
- private final Map<String, Key> verificationKeys;
- private final String issuer;
- private boolean allowNoExpiryClaim = false;
-
- public JsonWebTokenValidator(final Predicate<JsonWebToken> validation,
final Key verificationKey, final String issuer, final Map<String, Key>
verificationKeys, final boolean allowNoExpiryClaim) {
- this.validation = validation;
- this.verificationKey = verificationKey;
- this.verificationKeys = verificationKeys;
- this.issuer = issuer;
- this.allowNoExpiryClaim = allowNoExpiryClaim;
- }
-
- public JsonWebToken validate(final String token) throws ParseException {
- final JWTAuthConfiguration authConfiguration = verificationKey != null
? JWTAuthConfiguration.authConfiguration(verificationKey, issuer,
allowNoExpiryClaim) : JWTAuthConfiguration.authConfiguration(verificationKeys,
issuer, allowNoExpiryClaim);
- JWTCallerPrincipal principal;
-
- try {
- final JwtConsumerBuilder builder = new JwtConsumerBuilder()
- .setRelaxVerificationKeyValidation()
- .setRequireSubject()
- .setSkipDefaultAudienceValidation()
- .setJwsAlgorithmConstraints(
- new
AlgorithmConstraints(AlgorithmConstraints.ConstraintType.WHITELIST,
- AlgorithmIdentifiers.RSA_USING_SHA256,
- AlgorithmIdentifiers.RSA_USING_SHA384,
- AlgorithmIdentifiers.RSA_USING_SHA512
- ));
-
- if (authConfiguration.getIssuer() != null) {
- builder.setExpectedIssuer(authConfiguration.getIssuer());
- }
- if (authConfiguration.getExpGracePeriodSecs() > 0) {
-
builder.setAllowedClockSkewInSeconds(authConfiguration.getExpGracePeriodSecs());
- } else {
- builder.setEvaluationTime(NumericDate.fromSeconds(0));
- }
-
- if (authConfiguration.isSingleKey()) {
- builder.setVerificationKey(authConfiguration.getPublicKey());
- } else {
- builder.setVerificationKeyResolver(new
JwksVerificationKeyResolver(authConfiguration.getPublicKeysJwk()));
- }
-
- final JwtConsumer jwtConsumer = builder.build();
- final JwtContext jwtContext = jwtConsumer.process(token);
- final String type =
jwtContext.getJoseObjects().get(0).getHeader("typ");
- // Validate the JWT and process it to the Claims
- jwtConsumer.processContext(jwtContext);
- JwtClaims claimsSet = jwtContext.getJwtClaims();
-
- // We have to determine the unique name to use as the principal
name. It comes from upn, preferred_username, sub in that order
- String principalName = claimsSet.getClaimValue("upn",
String.class);
- if (principalName == null) {
- principalName = claimsSet.getClaimValue("preferred_username",
String.class);
- if (principalName == null) {
- principalName = claimsSet.getSubject();
- }
- }
- claimsSet.setClaim(Claims.raw_token.name(), token);
- principal = new JWTCallerPrincipal(token, type, claimsSet,
principalName);
-
- } catch (final InvalidJwtException e) {
- VALIDATION.warning(e.getMessage());
- throw new ParseException("Failed to verify token", e);
-
- } catch (final MalformedClaimException e) {
- VALIDATION.warning(e.getMessage());
- throw new ParseException("Failed to verify token claims", e);
- }
-
- return principal;
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- public static class Builder {
-
- private Predicate<JsonWebToken> validation = jsonWebToken -> true;
- private Key verificationKey;
- private List<JsonWebKey> verificationKeys;
- private String issuer;
- private boolean allowNoExpiryClaim = false;
-
- public Builder add(final Predicate<JsonWebToken> validation) {
- this.validation = validation.and(validation);
- return this;
- }
-
- public Builder publicKey(final String keyContent) {
- final Map<String, Key> keys = new
KeyResolver().readPublicKeys(keyContent);
- final Map.Entry<String, Key> key =
keys.entrySet().iterator().next();
- return verificationKey(key.getValue());
- }
-
- public Builder verificationKey(final Key key) {
- this.verificationKey = key;
- return this;
- }
-
- public Builder verificationKey(final Map<String, Key> key) {
- this.verificationKeys = verificationKeys;
- return this;
- }
-
- public JsonWebTokenValidator build() {
- return new JsonWebTokenValidator(validation, verificationKey,
issuer, null, allowNoExpiryClaim);
- }
-
- public Builder verificationKeys(final List<JsonWebKey> keys) {
- verificationKeys = keys;
- return this;
- }
-
- public Builder issuer(final String iss) {
- issuer = iss;
- return this;
- }
-
- public Builder allowNoExpiryClaim(final boolean allowNoExpiryClaim) {
- this.allowNoExpiryClaim = allowNoExpiryClaim;
- return this;
- }
-
-
- }
-}
diff --git
a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthConfiguration.java
b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthConfiguration.java
index b41a808a91..96986b2d02 100644
---
a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthConfiguration.java
+++
b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthConfiguration.java
@@ -16,20 +16,14 @@
*/
package org.apache.tomee.microprofile.jwt.config;
-import org.apache.tomee.microprofile.jwt.MPJWTFilter;
-import org.jose4j.jwk.JsonWebKey;
-
import java.security.Key;
import java.util.Collections;
-import java.util.List;
import java.util.Map;
-import java.util.logging.Logger;
/**
* The public key and expected issuer needed to validate a token.
*/
public class JWTAuthConfiguration {
- private static final Logger logger =
Logger.getLogger(JWTAuthConfiguration.class.getName());
public static final String DEFAULT_KEY = "DEFAULT";
private Map<String, Key> publicKeys;
@@ -42,13 +36,6 @@ public class JWTAuthConfiguration {
private boolean allowNoExpiryClaim = false;
private String cookieName = "Bearer";
- private JWTAuthConfiguration(final Key publicKey, final String issuer,
final boolean allowNoExpiryClaim, final String[] audiences) {
- this.publicKeys = Collections.singletonMap(DEFAULT_KEY, publicKey);
- this.issuer = issuer;
- this.allowNoExpiryClaim = allowNoExpiryClaim;
- this.audiences = audiences;
- }
-
public JWTAuthConfiguration(final Map<String, Key> publicKeys, final
String issuer, final boolean allowNoExpiryClaim, final String[] audiences,
final Map<String, Key> decryptKeys, final String header, final String cookie) {
if (publicKeys == null) {
this.publicKeys = Collections.EMPTY_MAP;
@@ -64,7 +51,7 @@ public class JWTAuthConfiguration {
} else {
this.decryptKeys = Collections.unmodifiableMap(decryptKeys);
}
-
+
this.issuer = issuer;
this.allowNoExpiryClaim = allowNoExpiryClaim;
this.audiences = audiences;
@@ -72,22 +59,6 @@ public class JWTAuthConfiguration {
this.cookieName = cookie;
}
- public static JWTAuthConfiguration authConfiguration(final Key publicKey,
final String issuer, final boolean allowNoExpiryClaim) {
- return new JWTAuthConfiguration(publicKey, issuer, allowNoExpiryClaim,
new String[0]);
- }
-
- public static JWTAuthConfiguration authConfiguration(final Map<String,
Key> publicKeys, final String issuer, final boolean allowNoExpiryClaim) {
- return authConfiguration(publicKeys, issuer, allowNoExpiryClaim, new
String[0]);
- }
-
- public static JWTAuthConfiguration authConfiguration(final Map<String,
Key> publicKeys, final String issuer, final boolean allowNoExpiryClaim, final
String[] audiences) {
- return authConfiguration(publicKeys, issuer, allowNoExpiryClaim,
audiences, null);
- }
-
- public static JWTAuthConfiguration authConfiguration(final Map<String,
Key> publicKeys, final String issuer, final boolean allowNoExpiryClaim, final
String[] audiences, final Map<String, Key> decryptKeys) {
- return new JWTAuthConfiguration(publicKeys, issuer,
allowNoExpiryClaim, audiences, decryptKeys, null, null);
- }
-
public String getCookieName() {
return cookieName;
}
@@ -96,10 +67,6 @@ public class JWTAuthConfiguration {
return audiences;
}
- public boolean isSingleKey() {
- return publicKeys.size() == 1;
- }
-
public Key getPublicKey() {
return publicKeys.get(DEFAULT_KEY);
}
@@ -112,10 +79,6 @@ public class JWTAuthConfiguration {
return decryptKeys;
}
- public List<JsonWebKey> getPublicKeysJwk() {
- return MPJWTFilter.ValidateJSonWebToken.asJwks(publicKeys);
- }
-
public String getIssuer() {
return issuer;
}
@@ -124,31 +87,16 @@ public class JWTAuthConfiguration {
return expGracePeriodSecs;
}
- public void setExpGracePeriodSecs(final int expGracePeriodSecs) {
- this.expGracePeriodSecs = expGracePeriodSecs;
- }
-
public String getHeaderName() {
return headerName;
}
- public void setHeaderName(final String headerName) {
- this.headerName = headerName;
- }
-
public String getHeaderScheme() {
return headerScheme;
}
- public void setHeaderScheme(final String headerScheme) {
- this.headerScheme = headerScheme;
- }
-
public boolean isAllowNoExpiryClaim() {
return allowNoExpiryClaim;
}
- public void setAllowNoExpiryClaim(boolean allowNoExpiryClaim) {
- this.allowNoExpiryClaim = allowNoExpiryClaim;
- }
}
diff --git
a/mp-jwt/src/test/java/org/apache/tomee/microprofile/jwt/JsonWebTokenValidatorTest.java
b/mp-jwt/src/test/java/org/apache/tomee/microprofile/jwt/JsonWebTokenValidatorTest.java
deleted file mode 100644
index 1be4da05be..0000000000
---
a/mp-jwt/src/test/java/org/apache/tomee/microprofile/jwt/JsonWebTokenValidatorTest.java
+++ /dev/null
@@ -1,49 +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.tomee.microprofile.jwt;
-
-import org.eclipse.microprofile.jwt.JsonWebToken;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class JsonWebTokenValidatorTest {
-
- @Test
- @Ignore
- public void testValidate() throws Exception {
-
- final JsonWebTokenValidator validator = JsonWebTokenValidator.builder()
-
.publicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEqFyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwRTYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5eUF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYnsIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9xnQIDAQAB")
- .build();
-
- final String claims = "{" +
- " \"sub\":\"Jane Awesome\"," +
- " \"iss\":\"https://server.example.com\"," +
- " \"groups\":[\"manager\",\"user\"]," +
- " \"exp\":2552047942" +
- "}";
- final String token = Tokens.asToken(claims);
-
- final JsonWebToken jwt = validator.validate(token);
-
- assertEquals("Jane Awesome", jwt.getSubject());
- assertEquals("https://server.example.com", jwt.getIssuer());
- assertEquals(2552047942l, jwt.getExpirationTime());
- }
-}
\ No newline at end of file
diff --git
a/mp-jwt/src/test/java/org/apache/tomee/microprofile/jwt/bval/ValidationConstraintsTest.java
b/mp-jwt/src/test/java/org/apache/tomee/microprofile/jwt/bval/ValidationConstraintsTest.java
deleted file mode 100644
index 8b2ff1887a..0000000000
---
a/mp-jwt/src/test/java/org/apache/tomee/microprofile/jwt/bval/ValidationConstraintsTest.java
+++ /dev/null
@@ -1,244 +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.tomee.microprofile.jwt.bval;
-
-import org.apache.tomee.microprofile.jwt.JsonWebTokenValidator;
-import org.apache.tomee.microprofile.jwt.Tokens;
-import org.apache.tomee.microprofile.jwt.bval.ann.Audience;
-import org.apache.tomee.microprofile.jwt.bval.ann.Issuer;
-import org.eclipse.microprofile.jwt.JsonWebToken;
-import org.junit.Assert;
-import org.junit.Test;
-
-import jakarta.annotation.security.RolesAllowed;
-import jakarta.validation.ConstraintValidator;
-import jakarta.validation.ConstraintValidatorContext;
-import jakarta.validation.ConstraintViolation;
-import jakarta.validation.Payload;
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-public class ValidationConstraintsTest {
-
- @Test
- public void invalidAudAndIss() throws Exception {
- final ValidationConstraints constraints =
ValidationConstraints.of(Circle.class);
-
- final Method red = Circle.class.getMethod("red");
-
-
- final JsonWebTokenValidator validator = JsonWebTokenValidator.builder()
- .publicKey(Tokens.getPublicKey())
- .build();
-
- final String claims = "{" +
- " \"sub\":\"Jane Awesome\"," +
- " \"iss\":\"http://something.com\"," +
- " \"groups\":[\"manager\",\"user\"]," +
- " \"exp\":2552047942" +
- "}";
- final String token = Tokens.asToken(claims);
-
- final JsonWebToken jwt = validator.validate(token);
-
- assertViolations(constraints.validate(red, jwt),
- "The 'aud' claim is required",
- "The 'aud' claim must contain 'bar'",
- "The 'iss' claim must be 'http://foo.bar.com'"
- );
- }
-
- @Test
- public void invalidIss() throws Exception {
- final ValidationConstraints constraints =
ValidationConstraints.of(Circle.class);
-
- final Method red = Circle.class.getMethod("red");
-
-
- final JsonWebTokenValidator validator = JsonWebTokenValidator.builder()
- .publicKey(Tokens.getPublicKey())
- .build();
-
- final String claims = "{" +
- " \"sub\":\"Jane Awesome\"," +
- " \"aud\":[\"bar\",\"user\"]," +
- " \"iss\":\"http://something.com\"," +
- " \"groups\":[\"manager\",\"user\"]," +
- " \"exp\":2552047942" +
- "}";
- final String token = Tokens.asToken(claims);
-
- final JsonWebToken jwt = validator.validate(token);
-
- assertViolations(constraints.validate(red, jwt),
- "The 'iss' claim must be 'http://foo.bar.com'"
- );
- }
-
- @Test
- public void invalidAud() throws Exception {
- final ValidationConstraints constraints =
ValidationConstraints.of(Circle.class);
-
- final Method red = Circle.class.getMethod("red");
-
-
- final JsonWebTokenValidator validator = JsonWebTokenValidator.builder()
- .publicKey(Tokens.getPublicKey())
- .build();
-
- final String claims = "{" +
- " \"sub\":\"Jane Awesome\"," +
- " \"aud\":[\"foo\",\"user\"]," +
- " \"iss\":\"http://foo.bar.com\"," +
- " \"groups\":[\"manager\",\"user\"]," +
- " \"exp\":2552047942" +
- "}";
- final String token = Tokens.asToken(claims);
-
- final JsonWebToken jwt = validator.validate(token);
-
- assertViolations(constraints.validate(red, jwt),
- "The 'aud' claim must contain 'bar'"
- );
- }
-
- @Test
- public void missingAud() throws Exception {
- final ValidationConstraints constraints =
ValidationConstraints.of(Circle.class);
-
- final Method red = Circle.class.getMethod("red");
-
-
- final JsonWebTokenValidator validator = JsonWebTokenValidator.builder()
- .publicKey(Tokens.getPublicKey())
- .build();
-
- final String claims = "{" +
- " \"sub\":\"Jane Awesome\"," +
- " \"iss\":\"http://foo.bar.com\"," +
- " \"groups\":[\"manager\",\"user\"]," +
- " \"exp\":2552047942" +
- "}";
- final String token = Tokens.asToken(claims);
-
- final JsonWebToken jwt = validator.validate(token);
-
- assertViolations(constraints.validate(red, jwt),
- "The 'aud' claim is required",
- "The 'aud' claim must contain 'bar'"
- );
- }
-
- @Test
- public void valid() throws Exception {
- final ValidationConstraints constraints =
ValidationConstraints.of(Circle.class);
-
- final Method red = Circle.class.getMethod("red");
-
-
- final JsonWebTokenValidator validator = JsonWebTokenValidator.builder()
- .publicKey(Tokens.getPublicKey())
- .build();
-
- final String claims = "{" +
- " \"sub\":\"Jane Awesome\"," +
- " \"iss\":\"http://foo.bar.com\"," +
- " \"aud\":[\"bar\",\"user\"]," +
- " \"groups\":[\"manager\",\"user\"]," +
- " \"exp\":2552047942" +
- "}";
- final String token = Tokens.asToken(claims);
-
- final JsonWebToken jwt = validator.validate(token);
-
- assertViolations(constraints.validate(red, jwt));
- }
-
- private static void assertViolations(final
Set<ConstraintViolation<Object>> constraintViolations, final String...
violations) {
- final List<String> actual = constraintViolations.stream()
- .map(ConstraintViolation::getMessage)
- .sorted()
- .collect(Collectors.toList());
-
- final List<String> expected = Stream.of(violations)
- .sorted()
- .collect(Collectors.toList());
-
- Assert.assertEquals(expected, actual);
- }
-
- public static class Circle {
- @Audience("bar")
- @Issuer("http://foo.bar.com")
- @Crimson()
- @RolesAllowed("") // to ensur non bean-validation annotations do not
cause errors
- public Red red() {
- return new Red();
- }
-
- /**
- * To ensure non bean-validation methods do not cause errors
- */
- @RolesAllowed("")
- public Object green() {
- return new Red();
- }
-
- /**
- * To ensure non-public methods do not cause errors
- */
- private Object blue() {
- return new Red();
- }
- }
-
- public static class Red {
- }
-
- @Documented
- @jakarta.validation.Constraint(validatedBy = {Crimson.Constraint.class})
- @Target({METHOD, FIELD, ANNOTATION_TYPE, PARAMETER})
- @Retention(RUNTIME)
- public @interface Crimson {
-
- Class<?>[] groups() default {};
-
- String message() default "This will never pass";
-
- Class<? extends Payload>[] payload() default {};
-
-
- class Constraint implements ConstraintValidator<Crimson, Red> {
- @Override
- public boolean isValid(final Red value, final
ConstraintValidatorContext context) {
- return false;
- }
- }
- }
-}
\ No newline at end of file