blob: 3c20205e4bc6ac8726d87f6eedfedff184de1429 [file] [log] [blame]
/*
* 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.deltaspike.beanvalidation.impl;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorFactory;
import javax.validation.Validation;
import org.apache.deltaspike.core.api.provider.BeanProvider;
import org.apache.deltaspike.core.util.ReflectionUtils;
/**
* A factory for creating CDI Aware/Enabled ConstraintValidators.
*
*/
public class CDIAwareConstraintValidatorFactory implements
ConstraintValidatorFactory
{
private static final String RELEASE_INSTANCE_METHOD_NAME = "releaseInstance";
private static volatile Boolean releaseInstanceMethodFound;
private static Method releaseInstanceMethod;
private final Logger log = Logger.getLogger(CDIAwareConstraintValidatorFactory.class.getName());
private final ConstraintValidatorFactory delegate;
public CDIAwareConstraintValidatorFactory()
{
delegate = Validation.byDefaultProvider().configure().getDefaultConstraintValidatorFactory();
if (log.isLoggable(Level.CONFIG))
{
log.config("Setting up delegate ConstraintValidatorFactory as " +
delegate.getClass().getCanonicalName());
}
}
@Override
public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> validatorClass)
{
T resolvedInst = BeanProvider.getContextualReference(validatorClass, true);
if (resolvedInst == null)
{
if (log.isLoggable(Level.CONFIG))
{
log.config("No contextual instances found for class " + validatorClass.getCanonicalName() +
" delegating to DefaultProvider behavior.");
}
resolvedInst = this.delegate.getInstance(validatorClass);
}
return resolvedInst;
}
//BV v1.1+
public void releaseInstance(ConstraintValidator<?, ?> constraintValidator)
{
if (releaseInstanceMethodFound == null)
{
lazyInit();
}
if (Boolean.TRUE.equals(releaseInstanceMethodFound))
{
ReflectionUtils.invokeMethod(this.delegate, releaseInstanceMethod, Void.class, true, constraintValidator);
}
}
private synchronized void lazyInit()
{
if (releaseInstanceMethodFound != null)
{
return;
}
Class<?> currentClass = delegate.getClass();
while (currentClass != null && !Object.class.getName().equals(currentClass.getName()))
{
for (Method currentMethod : currentClass.getDeclaredMethods())
{
if (RELEASE_INSTANCE_METHOD_NAME.equals(currentMethod.getName()) &&
currentMethod.getParameterTypes().length == 1 &&
currentMethod.getParameterTypes()[0].equals(ConstraintValidator.class))
{
releaseInstanceMethod = currentMethod;
releaseInstanceMethodFound = true;
return;
}
}
currentClass = currentClass.getSuperclass();
}
releaseInstanceMethodFound = false;
}
}