/******************************************************************************* * Copyright (c) 1998, 2015 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 v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * 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; } } } 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. */ 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); } } }