blob: 4e5bd50bdacac46f022cbab85f98eb16faee52c8 [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:
// mmacivor - March 10/2009 - Initial implementation
package org.eclipse.persistence.internal.jaxb;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.descriptors.InstantiationPolicy;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;
/**
* Purpose:
* Provide a version of Instantiation Policy that can make use of a multiple argument factory method.
* The defaultValues specified on this policy will be passed in to the factory method for the parameter values.
*
* This is required for certain JAXB generated classes that have no 0 arg constructor and a factory method with multiple arguments.
* @author mmacivor
*
*/
public class MultiArgInstantiationPolicy extends InstantiationPolicy {
private String[] parameterTypeNames;
private Class<?>[] parameterTypes;
private Object[] defaultValues;
public void setParameterTypeNames(String[] parameterTypeNames) {
this.parameterTypeNames = parameterTypeNames;
}
public void setParameterTypes(Class<?>[] parameterTypes) {
this.parameterTypes = parameterTypes;
}
public void setDefaultValues(Object[] values) {
defaultValues = values;
}
@Override
public void convertClassNamesToClasses(ClassLoader loader) {
super.convertClassNamesToClasses(loader);
if(parameterTypes == null) {
if(parameterTypeNames != null) {
Class<?>[] values = new Class<?>[parameterTypeNames.length];
for(int i = 0; i < values.length; i++) {
try{
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
try {
values[i] = AccessController.doPrivileged(new PrivilegedClassForName<>(parameterTypeNames[i], true, loader));
} catch (PrivilegedActionException exception) {
throw ValidationException.classNotFoundWhileConvertingClassNames(parameterTypeNames[i], exception.getException());
}
} else {
values[i] = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(parameterTypeNames[i], true, loader);
}
} catch (ClassNotFoundException exc){
throw ValidationException.classNotFoundWhileConvertingClassNames(factoryClassName, exc);
}
}
this.parameterTypes = values;
}
}
}
@Override
protected void initializeMethod() throws DescriptorException {
Class<?> tempClass;
if (this.getFactory() != null) {
tempClass = this.getFactory().getClass();
} else if (this.getFactoryClass() == null) {
tempClass = this.getDescriptor().getJavaClass();
} else {
tempClass = this.getFactoryClass();
}
if(this.parameterTypes == null) {
this.setMethod(this.buildMethod(tempClass, this.getMethodName(), new Class<?>[0]));
} else {
this.setMethod(this.buildMethod(tempClass, this.getMethodName(), this.parameterTypes));
}
}
/**
* Build and return a new instance, using the factory.
* The factory can be null, in which case the method is a static method defined by the descriptor class.
*/
@Override
protected Object buildNewInstanceUsingFactory() throws DescriptorException {
try {
// If the method is static, the first argument is ignored and can be null
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
try {
return AccessController.doPrivileged(new PrivilegedMethodInvoker(getMethod(), getFactory(), this.defaultValues));
} catch (PrivilegedActionException exception) {
Exception throwableException = exception.getException();
if (throwableException instanceof IllegalAccessException) {
throw DescriptorException.illegalAccessWhileMethodInstantiation(getMethod().toString(), this.getDescriptor(), throwableException);
} else {
throw DescriptorException.targetInvocationWhileMethodInstantiation(getMethod().toString(), this.getDescriptor(), throwableException);
}
}
} else {
return PrivilegedAccessHelper.invokeMethod(getMethod(), getFactory(), this.defaultValues);
}
} catch (IllegalAccessException exception) {
throw DescriptorException.illegalAccessWhileMethodInstantiation(getMethod().toString(), this.getDescriptor(), exception);
} catch (InvocationTargetException exception) {
throw DescriptorException.targetInvocationWhileMethodInstantiation(getMethod().toString(), this.getDescriptor(), exception);
} catch (NullPointerException exception) {
// Some JVMs will throw a NULL pointer exception here
throw DescriptorException.nullPointerWhileMethodInstantiation(this.getMethod().toString(), this.getDescriptor(), exception);
}
}
}