blob: e8cda9a139f71d044d75e7a656d6d6df862fb1ce [file] [log] [blame]
/*
* Copyright (c) 2019, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0, which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
package org.glassfish.jaxb.runtime.v2.runtime.reflect.opt;
import org.junit.Assert;
import org.junit.Test;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Unmarshaller;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlTransient;
import java.io.StringReader;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
* Test flag for disabling optimization
* org.glassfish.jaxb.runtime.v2.runtime.reflect.opt.OptimizedAccessorFactory.noOptimization=true/false
*
* @author Daniel Kec
*/
public class OptimizationTest {
private static final String EXPECTED_ACCESSOR_CLASS_REF = Book.class.getName() + "$JaxbAccessorM_getAuthor_setAuthor_java_lang_String";
private static final String OPTIMIZATION_ON = "AUTHOR_EXPECTING_OPTIMIZATION_ON";
private static final String OPTIMIZATION_OFF = "AUTHOR_EXPECTING_OPTIMIZATION_OFF";
private static final VarHandle MODIFIERS;
static {
try {
MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup());
MODIFIERS = lookup.findVarHandle(Field.class, "modifiers", int.class);
} catch (IllegalAccessException | NoSuchFieldException ex) {
throw new RuntimeException(ex);
}
}
@Test
public void checkNoOptimizationFlagFalse() throws JAXBException {
Book book = unmarshal(OPTIMIZATION_ON);
Assert.assertTrue(book.errorMessage, book.errorMessage == null);
Assert.assertEquals(OPTIMIZATION_ON, book.getAuthor());
}
@Test
public void checkNoOptimizationFlagTrue() throws JAXBException, NoSuchFieldException, IllegalAccessException {
try {
setNoOptimizationFlag(true);
Book book = unmarshal(OPTIMIZATION_OFF);
Assert.assertTrue(book.errorMessage, book.errorMessage == null);
Assert.assertEquals(OPTIMIZATION_OFF, book.getAuthor());
} finally {
setNoOptimizationFlag(false);
}
}
private Book unmarshal(String autor) throws JAXBException {
JAXBContext context = JAXBContext.newInstance(Book.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
return (Book) unmarshaller.unmarshal(new StringReader(
String.format("<book><author>%s</author></book>", autor)));
}
private void setNoOptimizationFlag(boolean flag) throws NoSuchFieldException, IllegalAccessException {
Field noOptimizationField = OptimizedAccessorFactory.class.getField("noOptimization");
noOptimizationField.setAccessible(true);
if (Modifier.isFinal(noOptimizationField.getModifiers())) {
MODIFIERS.set(noOptimizationField, noOptimizationField.getModifiers() & ~Modifier.FINAL);
}
noOptimizationField.setBoolean(OptimizedAccessorFactory.class, true);
}
@XmlRootElement
static class Book {
private String author;
@XmlTransient
String errorMessage = null;
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
String artificialInnerClass = null;
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
for (StackTraceElement el : stackTrace) {
System.out.println(el.toString());
if (el.getClassName().equals(EXPECTED_ACCESSOR_CLASS_REF)) {
artificialInnerClass = el.getClassName();
break;
}
}
if (author.equals(OPTIMIZATION_OFF) && artificialInnerClass != null) {
this.errorMessage = String.format("Artificial accessor class detected %s", artificialInnerClass);
} else if (author.equals(OPTIMIZATION_ON) && artificialInnerClass == null) {
this.errorMessage = String.format("Expected artificial accessor class not found: %s", EXPECTED_ACCESSOR_CLASS_REF);
}
this.author = author;
}
}
}