| /* |
| * Copyright (c) 2015, 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: |
| // Marcel Valovy - initial implementation |
| package org.eclipse.persistence.testing.jaxb.beanvalidation; |
| |
| import org.eclipse.persistence.exceptions.BeanValidationException; |
| import org.eclipse.persistence.jaxb.ConstraintViolationWrapper; |
| import org.eclipse.persistence.jaxb.JAXBContext; |
| import org.eclipse.persistence.jaxb.JAXBContextFactory; |
| import org.eclipse.persistence.jaxb.JAXBMarshaller; |
| import org.eclipse.persistence.testing.jaxb.beanvalidation.special.ExternallyConstrainedEmployee; |
| import org.eclipse.persistence.testing.jaxb.beanvalidation.special.ExternallyConstrainedEmployee2; |
| import org.junit.After; |
| import org.junit.Before; |
| |
| import jakarta.validation.Validation; |
| import java.io.StringWriter; |
| import java.lang.reflect.Field; |
| import java.net.URL; |
| import java.util.Set; |
| |
| /** |
| * |
| * @author Marcel Valovy - marcel.valovy@oracle.com |
| */ |
| public class ValidationXMLTestCase extends junit.framework.TestCase { |
| |
| private static final String NOT_NULL_MESSAGE = "{jakarta.validation.constraints.NotNull.message}"; |
| private static final String MIN_MESSAGE = "{jakarta.validation.constraints.Min.message}"; |
| private static final String MOXY_JAXBCONTEXT_FACTORY = JAXBContextFactory.class.getName(); |
| private static final String SYSTEM_PROPERTY_JAXBCONTEXT = "jakarta.xml.bind.JAXBContext"; |
| private static final String VALIDATION_XML = "META-INF/validation.xml"; |
| private static final String CONSTRAINTS_XML = "META-INF/validation/constraints.xml"; |
| private static final String CONSTRAINTS2_XML = "META-INF/validation/constraints2.xml"; |
| private static final String VALIDATION_XML_PATH = "org/eclipse/persistence/testing/jaxb/beanvalidation/validation.xml"; |
| private static final String CONSTRAINTS_XML_PATH = "org/eclipse/persistence/testing/jaxb/beanvalidation/constraints.xml"; |
| private static final String CONSTRAINTS2_XML_PATH = "org/eclipse/persistence/testing/jaxb/beanvalidation/constraints2.xml"; |
| private static final boolean DEBUG = false; |
| |
| private ClassLoader classLoader; |
| private Thread currentThread = Thread.currentThread(); |
| |
| private static final class ValidationClassLoader extends ClassLoader { |
| ValidationClassLoader(ClassLoader parent) { |
| super(parent); |
| } |
| |
| @Override |
| public URL getResource(String name) { |
| if (name != null) { |
| switch (name) { |
| case VALIDATION_XML: |
| return getParent().getResource(VALIDATION_XML_PATH); |
| case CONSTRAINTS_XML: |
| return getParent().getResource(CONSTRAINTS_XML_PATH); |
| case CONSTRAINTS2_XML: |
| return getParent().getResource(CONSTRAINTS2_XML_PATH); |
| } |
| } |
| return super.getResource(name); |
| } |
| } |
| |
| /** |
| * Tests fix for endless invocation loop between |
| * unmarshaller - validator - unmarshaller. |
| * File {@link #VALIDATION_XML} must be present on classpath. |
| */ |
| public void testEndlessLoopInvocations() throws Exception { |
| final String previous = System.getProperty(SYSTEM_PROPERTY_JAXBCONTEXT); |
| try { |
| System.setProperty(SYSTEM_PROPERTY_JAXBCONTEXT, MOXY_JAXBCONTEXT_FACTORY); |
| assertEquals(MOXY_JAXBCONTEXT_FACTORY, System.getProperty(SYSTEM_PROPERTY_JAXBCONTEXT)); |
| |
| if (DEBUG) System.out.println("System property \"" + SYSTEM_PROPERTY_JAXBCONTEXT + |
| "\"'s value has been set to " + System.getProperty(SYSTEM_PROPERTY_JAXBCONTEXT)); |
| |
| Validation.buildDefaultValidatorFactory(); |
| } finally { |
| final String clearedProperty = previous != null |
| ? System.setProperty(SYSTEM_PROPERTY_JAXBCONTEXT, previous) |
| : System.clearProperty(SYSTEM_PROPERTY_JAXBCONTEXT); |
| |
| assertEquals(MOXY_JAXBCONTEXT_FACTORY, clearedProperty); |
| |
| if (DEBUG) System.out.println("System property \"" + SYSTEM_PROPERTY_JAXBCONTEXT |
| + "\"'s value has been cleared," |
| + "unless it previously was set, in which case it's original value has been restored."); |
| } |
| } |
| |
| /** |
| * Tests that we do not skip validation on classes that are constrained through validation.xml. |
| */ |
| public void testExternalConstraints() throws Exception { |
| JAXBMarshaller marshaller = (JAXBMarshaller) JAXBContextFactory.createContext(new |
| Class<?>[]{ExternallyConstrainedEmployee.class, ExternallyConstrainedEmployee2.class}, |
| null).createMarshaller(); |
| ExternallyConstrainedEmployee employee = new ExternallyConstrainedEmployee().withId(null).withAge(15); |
| ExternallyConstrainedEmployee2 employee2 = new ExternallyConstrainedEmployee2().withId(null).withAge(15); |
| |
| try { |
| marshaller.marshal(employee, new StringWriter()); |
| } catch (BeanValidationException ignored) { |
| } |
| |
| Set<ConstraintViolationWrapper<Object>> violations = marshaller.getConstraintViolations(); |
| |
| try { |
| marshaller.marshal(employee2, new StringWriter()); |
| } catch (BeanValidationException ignored) { |
| } |
| |
| violations.addAll(marshaller.getConstraintViolations()); |
| |
| assertFalse("Some constraints were not validated, even though they should have been.", violations.isEmpty()); |
| |
| int i = 0; |
| for (ConstraintViolationWrapper<Object> cv : violations) { |
| if (NOT_NULL_MESSAGE.equals(cv.getMessageTemplate())) i += 0b1000; |
| if (MIN_MESSAGE.equals(cv.getMessageTemplate())) i += 0b0001; |
| } |
| assertTrue(i == 0b1001); |
| } |
| |
| @Override |
| @Before |
| public void setUp() throws Exception { |
| classLoader = new ValidationClassLoader(currentThread.getContextClassLoader()); |
| currentThread.setContextClassLoader(classLoader); |
| resetBeanValidation(); |
| } |
| |
| private void resetBeanValidation() throws Exception { |
| Field beanValidationHelper = JAXBContext.class.getDeclaredField("beanValidationHelper"); |
| Field beanValidationPresent = JAXBContext.class.getDeclaredField("beanValidationPresent"); |
| |
| beanValidationHelper.setAccessible(true); |
| beanValidationPresent.setAccessible(true); |
| |
| beanValidationHelper.set(JAXBContext.class, null); |
| beanValidationPresent.set(JAXBContext.class, null); |
| |
| beanValidationHelper.setAccessible(false); |
| beanValidationPresent.setAccessible(false); |
| } |
| |
| @Override |
| @After |
| public void tearDown() throws Exception { |
| currentThread.setContextClassLoader(classLoader.getParent()); |
| } |
| } |