001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017package org.apache.logging.log4j.core.config.plugins.validation; 018 019import java.lang.annotation.Annotation; 020import java.lang.reflect.ParameterizedType; 021import java.lang.reflect.Type; 022import java.util.ArrayList; 023import java.util.Collection; 024 025import org.apache.logging.log4j.core.util.ReflectionUtil; 026 027/** 028 * Utility class to locate an appropriate {@link ConstraintValidator} implementation for an annotation. 029 * 030 * @since 2.1 031 */ 032public final class ConstraintValidators { 033 034 private ConstraintValidators() { 035 } 036 037 /** 038 * Finds all relevant {@link ConstraintValidator} objects from an array of annotations. All validators will be 039 * {@link ConstraintValidator#initialize(java.lang.annotation.Annotation) initialized} before being returned. 040 * 041 * @param annotations the annotations to find constraint validators for 042 * @return a collection of ConstraintValidators for the given annotations 043 */ 044 public static Collection<ConstraintValidator<?>> findValidators(final Annotation... annotations) { 045 final Collection<ConstraintValidator<?>> validators = 046 new ArrayList<>(); 047 for (final Annotation annotation : annotations) { 048 final Class<? extends Annotation> type = annotation.annotationType(); 049 if (type.isAnnotationPresent(Constraint.class)) { 050 final ConstraintValidator<?> validator = getValidator(annotation, type); 051 if (validator != null) { 052 validators.add(validator); 053 } 054 } 055 } 056 return validators; 057 } 058 059 private static <A extends Annotation> ConstraintValidator<A> getValidator(final A annotation, 060 final Class<? extends A> type) { 061 final Constraint constraint = type.getAnnotation(Constraint.class); 062 final Class<? extends ConstraintValidator<?>> validatorClass = constraint.value(); 063 if (type.equals(getConstraintValidatorAnnotationType(validatorClass))) { 064 @SuppressWarnings("unchecked") // I don't think we could be any more thorough in validation here 065 final ConstraintValidator<A> validator = (ConstraintValidator<A>) 066 ReflectionUtil.instantiate(validatorClass); 067 validator.initialize(annotation); 068 return validator; 069 } 070 return null; 071 } 072 073 private static Type getConstraintValidatorAnnotationType(final Class<? extends ConstraintValidator<?>> type) { 074 for (final Type parentType : type.getGenericInterfaces()) { 075 if (parentType instanceof ParameterizedType) { 076 final ParameterizedType parameterizedType = (ParameterizedType) parentType; 077 if (ConstraintValidator.class.equals(parameterizedType.getRawType())) { 078 return parameterizedType.getActualTypeArguments()[0]; 079 } 080 } 081 } 082 return Void.TYPE; 083 } 084}