blob: 3e5da2e0103c9f3cd752d602cde010fc0bfeb9ee [file] [log] [blame]
/*
* Copyright (c) 1998, 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:
// Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.jaxb.compiler;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import jakarta.xml.bind.Marshaller;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.security.PrivilegedGetMethod;
/**
* INTERNAL:
* <p><b>Purpose:</b>Hold information about class based JAXB 2.0 Callback methods
* <p><b>Responsibilities:</b><ul>
* <li>Store information about domainClass and the callback methods</li>
* <li>Act as a means to integrate JAXB 2.0 Class based callbacks with TopLink OXM
* Listener based callbacks.</li></ul>
*
* A Map of MarshalCallbacks are created during JAXB 2.0 Generation and are set on a
* JAXBMarshallerListener on each JAXBMarshaller. These callbacks are used to invoke
* the JAXB 2.0 Class Based callbacks on each object at the appropriate time.
*
* @author mmacivor
* @since Oracle TopLink 11.1.1.0.0
* @see org.eclipse.persistence.jaxb.JAXBMarshalListener
* @see org.eclipse.persistence.jaxb.JAXBMarshaller
*/
public class MarshalCallback {
private Class domainClass;
private String domainClassName;
private Method beforeMarshalCallback;
private Method afterMarshalCallback;
private boolean hasBeforeMarshalCallback = false;
private boolean hasAfterMarshalCallback = false;
public Method getAfterMarshalCallback() {
return afterMarshalCallback;
}
public Method getBeforeMarshalCallback() {
return beforeMarshalCallback;
}
public Class getDomainClass() {
return domainClass;
}
/**
*/
public void initialize(ClassLoader loader) {
try {
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
try{
domainClass = AccessController.doPrivileged(new PrivilegedClassForName<>(domainClassName, true, loader));
}catch (PrivilegedActionException ex){
if (ex.getCause() instanceof ClassNotFoundException){
throw (ClassNotFoundException) ex.getCause();
}
throw (RuntimeException)ex.getCause();
}
}else{
domainClass = PrivilegedAccessHelper.getClassForName(domainClassName, true, loader);
}
} catch (ClassNotFoundException ex) {
return;
}
Class[] params = new Class[] { Marshaller.class };
if (hasBeforeMarshalCallback) {
try {
Method beforeMarshal = null;
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
try{
beforeMarshal = AccessController.doPrivileged(new PrivilegedGetMethod(domainClass, "beforeMarshal", params, false));
}catch (PrivilegedActionException ex){
if (ex.getCause() instanceof NoSuchMethodException){
throw (NoSuchMethodException) ex.getCause();
}
throw (RuntimeException)ex.getCause();
}
}else{
beforeMarshal = PrivilegedAccessHelper.getMethod(domainClass, "beforeMarshal", params, false);
}
setBeforeMarshalCallback(beforeMarshal);
} catch (NoSuchMethodException nsmex) {}
}
if (hasAfterMarshalCallback) {
try {
Method afterMarshal = null;
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
try{
afterMarshal = AccessController.doPrivileged(new PrivilegedGetMethod(domainClass, "afterMarshal", params, false));
}catch (PrivilegedActionException ex){
if (ex.getCause() instanceof NoSuchMethodException){
throw (NoSuchMethodException) ex.getCause();
}
throw (RuntimeException)ex.getCause();
}
}else{
afterMarshal = PrivilegedAccessHelper.getMethod(domainClass, "afterMarshal", params, false);
}
setAfterMarshalCallback(afterMarshal);
} catch (NoSuchMethodException nsmex) {}
}
}
/**
* Should not use this method - the init method will
* overwrite the set value.
*/
public void setAfterMarshalCallback(Method method) {
afterMarshalCallback = method;
}
public void setHasAfterMarshalCallback() {
hasAfterMarshalCallback = true;
}
/**
* Should not use this method - the init method will
* overwrite the set value.
*/
public void setBeforeMarshalCallback(Method method) {
beforeMarshalCallback = method;
}
public void setHasBeforeMarshalCallback() {
hasBeforeMarshalCallback = true;
}
/**
* Should use setDomainClassName - the init method will overwrite
* the set value with Class.forName(domainClassName).
*
*/
public void setDomainClass(Class clazz) {
domainClass = clazz;
setDomainClassName(clazz.getName());
}
public void setDomainClassName(String className) {
domainClassName = className;
}
}