blob: ee022db5e1eaa096fd916ea7ad39f84f42c50732 [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 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;
/**
* 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++) {
final String parameterTypeName = parameterTypeNames[i];
values[i] = PrivilegedAccessHelper.callDoPrivilegedWithException(
() -> org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(parameterTypeName, true, loader),
(ex) -> ValidationException.classNotFoundWhileConvertingClassNames(factoryClassName, ex)
);
}
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 {
return PrivilegedAccessHelper.callDoPrivilegedWithException(
() -> PrivilegedAccessHelper.invokeMethod(getMethod(), getFactory(), this.defaultValues),
(ex) -> {
if (ex instanceof IllegalAccessException) {
return DescriptorException.illegalAccessWhileMethodInstantiation(getMethod().toString(), this.getDescriptor(), ex);
} else if (ex instanceof InvocationTargetException) {
return DescriptorException.targetInvocationWhileMethodInstantiation(getMethod().toString(), this.getDescriptor(), ex);
} else if (ex instanceof NullPointerException) {
return DescriptorException.nullPointerWhileMethodInstantiation(this.getMethod().toString(), this.getDescriptor(), ex);
} else {
return new RuntimeException("Unexpected exception from MultiArgInstantiationPolicy.buildNewInstanceUsingFactory()", ex);
}
}
);
}
}