blob: 64643ec6527ecd2b73809a2aa556c7a3ab2f6bf2 [file] [log] [blame]
/*
* Copyright (c) 2009, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// 08/01/2012-2.5 Chris Delahunt
// - 371950: Metadata caching
package org.eclipse.persistence.internal.jpa.deployment;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.Map;
import jakarta.validation.Validation;
import jakarta.validation.ValidatorFactory;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.PersistenceUnitLoadingException;
import org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.sessions.AbstractSession;
/**
* Responsible for intialializing Bean Validation. The only expected instance of this interface is the inner class.
* @author Mitesh Meswani
*/
public interface BeanValidationInitializationHelper {
void bootstrapBeanValidation(Map puProperties, AbstractSession session, ClassLoader appClassLoader);
class BeanValidationInitializationHelperImpl implements BeanValidationInitializationHelper {
public BeanValidationInitializationHelperImpl() {
}
@Override
public void bootstrapBeanValidation(Map puProperties, AbstractSession session, ClassLoader appClassLoader) {
ValidatorFactory validatorFactory = getValidatorFactory(puProperties);
//Check user/environment has specified the validator factory
if (validatorFactory != null) {
// We could obtain a validator factory => Bean Validation API is available at runtime. It is ok to cast now
ValidatorFactory beanValidatorFactory = validatorFactory;
Class[] groupPrePersit = translateValidationGroups(
(String) puProperties.get(PersistenceUnitProperties.VALIDATION_GROUP_PRE_PERSIST), appClassLoader) ;
Class[] groupPreUpdate = translateValidationGroups(
(String) puProperties.get(PersistenceUnitProperties.VALIDATION_GROUP_PRE_UPDATE), appClassLoader);
Class[] groupPreRemove = translateValidationGroups(
(String) puProperties.get(PersistenceUnitProperties.VALIDATION_GROUP_PRE_REMOVE), appClassLoader);
BeanValidationListener validationListener =
new BeanValidationListener(beanValidatorFactory, groupPrePersit, groupPreUpdate, groupPreRemove);
//Install BeanValidationListener on the desc
for (ClassDescriptor descriptor : session.getProject().getOrderedDescriptors()) {
if (descriptor.isDescriptorTypeNormal()) {
//add only to entities
descriptor.getEventManager().addInternalListener(validationListener);
}
}
}
}
/**
* INTERNAL:
* @param puProperties merged properties for this persitence unit
* @return ValidatorFactory instance to be used for this persistence unit.
*/
private ValidatorFactory getValidatorFactory(Map puProperties) {
ValidatorFactory validatorFactory = (ValidatorFactory)puProperties.get(PersistenceUnitProperties.VALIDATOR_FACTORY);
if (validatorFactory == null) {
validatorFactory = Validation.buildDefaultValidatorFactory();
}
return validatorFactory;
}
/**
* INTERNAL:
* translate validation group specified as fully qualifed class names deliminated by ',' into Class[]
* @param validationGroups Array of "," deliminated fully qualified class names
* @param appClassLoader The classloader for application
* @return Array of classes corresponding to classnames in given <code>validationGroups</code>.
* <code>null</code> if given <code>validationGroups</code> is null or empty
*/
private Class[] translateValidationGroups(String validationGroups, ClassLoader appClassLoader) {
Class[] validationGroupsClasses = null;
if(validationGroups != null && validationGroups.length() != 0 ) {
String[] validationGroupClassNames = validationGroups.split(",");
validationGroupsClasses = new Class[validationGroupClassNames.length];
for(int i = 0; i < validationGroupClassNames.length; i++) {
String validationGroupClassName = validationGroupClassNames[i];
try {
validationGroupsClasses[i] = loadClass(validationGroupClassName, appClassLoader);
} catch (Exception e) {
throw PersistenceUnitLoadingException.exceptionLoadingClassWhileInitializingValidationGroups(validationGroupClassName, e);
}
}
}
return validationGroupsClasses;
}
/**
* Internal:
* Helper to load class.
* Please do not make this method protected or public else it would expose a security hole that would
* allow malicious code to use this method to load any class without security permission
* @param className Fully qualified class name
* @param classLoader ClassLoader to be used for loading the class
* @return Loaded Class
*/
private Class loadClass(String className, ClassLoader classLoader) throws PrivilegedActionException, ClassNotFoundException {
Class loadedClass = null;
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
loadedClass = AccessController.doPrivileged(
new PrivilegedClassForName<>(className, true, classLoader));
} else {
loadedClass = PrivilegedAccessHelper.getClassForName(className, true, classLoader);
}
return loadedClass;
}
}
}