All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 1998, 2024 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
//     08/23/2010-2.2 Michael O'Brien
//        - 323043: application.xml module ordering may cause weaving not to occur causing an NPE.
//                       warn if expected "_persistence_//_vh" method not found
//                       instead of throwing NPE during deploy validation.
//                       Note: SDO overrides this class so an override of getMethodReturnType
//                       will also need an override in SDO.
package org.eclipse.persistence.internal.descriptors;

import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.AttributeAccessor;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 

Purpose: A wrapper class for handling cases when the domain object attributes are * to be accessed thru the accessor methods. This could happen if the variables are not defined * public in the domain object. * * @author Sati * @since TOPLink/Java 1.0 */ public class MethodAttributeAccessor extends AttributeAccessor { protected String setMethodName = ""; protected String getMethodName; protected transient Method setMethod; protected transient Method getMethod; /** * Return the return type of the method accessor. */ @Override public Class getAttributeClass() { if (getGetMethod() == null) { return null; } return getGetMethodReturnType(); } /** * Gets the value of an instance variable in the object. */ @Override public Object getAttributeValueFromObject(Object anObject) throws DescriptorException { return getAttributeValueFromObject(anObject, null); } /** * Gets the value of an instance variable in the object. */ protected Object getAttributeValueFromObject(final Object anObject, final Object[] parameters) throws DescriptorException { return PrivilegedAccessHelper.callDoPrivilegedWithException( // PERF: Direct-var access. () -> getMethod.invoke(anObject, parameters), (ex) -> { if (ex instanceof IllegalArgumentException) { return DescriptorException.illegalArgumentWhileGettingValueThruMethodAccessor(getGetMethodName(), anObject.getClass().getName(), ex); } else if (ex instanceof IllegalAccessException) { return DescriptorException.illegalAccessWhileGettingValueThruMethodAccessor(getGetMethodName(), anObject.getClass().getName(), ex); } else if (ex instanceof InvocationTargetException) { return DescriptorException.targetInvocationWhileGettingValueThruMethodAccessor(getGetMethodName(), anObject.getClass().getName(), ex); } else if (ex instanceof NullPointerException) { // Some JVM's throw this exception for some very odd reason return DescriptorException.nullPointerWhileGettingValueThruMethodAccessor(getGetMethodName(), anObject.getClass().getName(), ex); } // This indicates unexpected problem in the code return new RuntimeException(String.format( "Invocation of %s getter method failed", getMethod.getName()), ex); } ); } /** * Return the accessor method for the attribute accessor. * 266912: For Metamodel API - change visibility from protected */ public Method getGetMethod() { return getMethod; } /** * Return the name of the accessor method for the attribute accessor. */ public String getGetMethodName() { return getMethodName; } /** * INTERNAL: * Return the GetMethod return type for this MethodAttributeAccessor. * A special check is made to determine if a missing method is a result of failed weaving. */ // Note: SDO overrides this method and will handle a null GetMethod public Class getGetMethodReturnType() throws DescriptorException { // 323403: If the getMethod is missing - check for "_persistence_*_vh" to see if weaving was expected if(null == getGetMethod() && null != getGetMethodName() && (getGetMethodName().contains(Helper.PERSISTENCE_FIELDNAME_PREFIX))) { // warn before a possible NPE on accessing a weaved method that does not exist AbstractSessionLog.getLog().log(SessionLog.FINEST, "no_weaved_vh_method_found_verify_weaving_and_module_order", getGetMethodName(), null, this); // 323403: We cannot continue to process objects that are not weaved - if weaving is enabled // If we allow the getMethodReturnType to continue - we will throw an obscure NullPointerException throw DescriptorException.nullPointerWhileGettingValueThruMethodAccessorCausedByWeavingNotOccurringBecauseOfModuleOrder(getGetMethodName(), "", null); } return PrivilegedAccessHelper.callDoPrivileged( () -> PrivilegedAccessHelper.getMethodReturnType(getGetMethod()) ); } /** * Return the set method for the attribute accessor. */ protected Method getSetMethod() { return setMethod; } /** * Return the name of the set method for the attribute accessor. */ public String getSetMethodName() { return setMethodName; } public Class getSetMethodParameterType() { return getSetMethodParameterType(0); } protected Class getSetMethodParameterType(int index) { return PrivilegedAccessHelper.callDoPrivileged( () ->PrivilegedAccessHelper.getMethodParameterTypes(getSetMethod())[index] ); } protected Class[] getSetMethodParameterTypes() { return new Class[] {getGetMethodReturnType()}; } /** * Set get and set method after creating these methods by using * get and set method names */ @Override public void initializeAttributes(Class theJavaClass) throws DescriptorException { initializeAttributes(theJavaClass, null); } /** * Set get and set method after creating these methods by using * get and set method names */ protected void initializeAttributes(Class theJavaClass, Class[] getParameterTypes) throws DescriptorException { if (getAttributeName() == null) { throw DescriptorException.attributeNameNotSpecified(); } try { setGetMethod(Helper.getDeclaredMethod(theJavaClass, getGetMethodName(), getParameterTypes)); // The parameter type for the set method must always be the return type of the get method. if(!isWriteOnly()) { setSetMethod(Helper.getDeclaredMethod(theJavaClass, getSetMethodName(), getSetMethodParameterTypes())); } } catch (NoSuchMethodException ex) { DescriptorException descriptorException = DescriptorException.noSuchMethodWhileInitializingAttributesInMethodAccessor(getSetMethodName(), getGetMethodName(), theJavaClass.getName()); descriptorException.setInternalException(ex); throw descriptorException; } catch (SecurityException exception) { DescriptorException descriptorException = DescriptorException.securityWhileInitializingAttributesInMethodAccessor(getSetMethodName(), getGetMethodName(), theJavaClass.getName()); descriptorException.setInternalException(exception); throw descriptorException; } } /** * Returns true if this attribute accessor has been initialized and now stores a reference to the * class's attribute. An attribute accessor can become uninitialized on serialization. */ @Override public boolean isInitialized(){ return (this.getMethod != null || isReadOnly()) && (this.setMethod != null || isWriteOnly()); } @Override public boolean isMethodAttributeAccessor() { return true; } /** * Sets the value of the instance variable in the object to the value. */ @Override public void setAttributeValueInObject(Object domainObject, Object attributeValue) throws DescriptorException { setAttributeValueInObject(domainObject, attributeValue, new Object[] {attributeValue}); } /** * Sets the value of the instance variable in the object to the value. */ protected void setAttributeValueInObject(final Object domainObject, final Object attributeValue, final Object[] parameters) throws DescriptorException { try { PrivilegedAccessHelper.callDoPrivilegedWithException( () -> this.setMethod.invoke(domainObject, parameters) ); } catch (IllegalAccessException exception) { throw DescriptorException.illegalAccessWhileSettingValueThruMethodAccessor(getSetMethodName(), attributeValue, exception); } catch (IllegalArgumentException exception) { // TODO: This code should be removed, it should not be required and may cause unwanted sideeffects. // Allow XML change set to merge correctly since new value in XML change set is always String try { if (attributeValue instanceof String) { final Object[] newParameters = new Object[] { ConversionManager.getDefaultManager().convertObject(attributeValue, getAttributeClass())}; PrivilegedAccessHelper.callDoPrivilegedWithException( () -> PrivilegedAccessHelper.invokeMethod(getSetMethod(), domainObject, newParameters) ); return; } } catch (Exception e) { // Do nothing and move on to throw the original exception } throw DescriptorException.illegalArgumentWhileSettingValueThruMethodAccessor(getSetMethodName(), attributeValue, exception); } catch (InvocationTargetException exception) { throw DescriptorException.targetInvocationWhileSettingValueThruMethodAccessor(getSetMethodName(), attributeValue, exception); } catch (NullPointerException exception) { // TODO: This code should be removed, it should not be required and may cause unwanted side effects. // cr 3737 If a null pointer was thrown because EclipseLink attempted to set a null reference into a // primitive creating a primitive of value 0 to set in the object. // Is this really the best place for this? is this not why we have null-value and conversion-manager? final Class fieldClass = getSetMethodParameterType(); //Found when fixing Bug2910086 if (fieldClass.isPrimitive() && (attributeValue == null)) { parameters[parameters.length - 1] = ConversionManager.getDefaultManager().convertObject(0, fieldClass); PrivilegedAccessHelper.callDoPrivilegedWithException( () -> PrivilegedAccessHelper.invokeMethod(getSetMethod(), domainObject, parameters), (ex) -> DescriptorException.nullPointerWhileSettingValueThruInstanceVariableAccessor(getAttributeName(), null, ex) ); } else { // Some JVM's throw this exception for some very odd reason // See throw DescriptorException.nullPointerWhileSettingValueThruInstanceVariableAccessor(getAttributeName(), attributeValue, exception); } // This indicates unexpected problem in the code } catch (Exception ex) { throw new RuntimeException(String.format("Invocation of %s setter method failed", getSetMethod().getName()), ex); } } /** * Set the accessor method for the attribute accessor. */ protected void setGetMethod(Method getMethod) { this.getMethod = getMethod; } /** * Set the name of the accessor method for the attribute accessor. */ public void setGetMethodName(String getMethodName) { this.getMethodName = getMethodName; } /** * Set the set method for the attribute accessor. */ protected void setSetMethod(Method setMethod) { this.setMethod = setMethod; } /** * Set the name of the set method for the attribute accessor. */ public void setSetMethodName(String setMethodName) { this.setMethodName = setMethodName; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy