Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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
// 02/02/2009-2.0 Chris delahunt
// - 241765: JPA 2.0 Derived identities
// 04/24/2009-2.0 Guy Pelletier
// - 270011: JPA 2.0 MappedById support
// 10/21/2009-2.0 Guy Pelletier
// - 290567: mappedbyid support incomplete
// 12/17/2010-2.2 Guy Pelletier
// - 330755: Nested embeddables can't be used as embedded ids
// 11/10/2011-2.4 Guy Pelletier
// - 357474: Address primaryKey option from tenant discriminator column
// 14/05/2012-2.4 Guy Pelletier
// - 376603: Provide for table per tenant support for multitenant applications
// 08/20/2012-2.4 Guy Pelletier
// - 381079: EclipseLink dynamic entity does not support embedded-id
package org.eclipse.persistence.internal.jpa;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.eclipse.persistence.annotations.CacheKeyType;
import org.eclipse.persistence.descriptors.CMPPolicy;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.identitymaps.CacheId;
import org.eclipse.persistence.internal.indirection.WeavedObjectBasicIndirectionPolicy;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.security.PrivilegedGetField;
import org.eclipse.persistence.internal.security.PrivilegedGetMethod;
import org.eclipse.persistence.internal.security.PrivilegedGetValueFromField;
import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;
import org.eclipse.persistence.internal.security.PrivilegedSetValueInField;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ObjectReferenceMapping;
import org.eclipse.persistence.mappings.OneToOneMapping;
import org.eclipse.persistence.mappings.foundation.AbstractColumnMapping;
/**
* Defines primary key extraction code for use in JPA. A descriptor should have a CMP3Policy
* attached to handle basic Id as well as IdClass/EmbeddedId usage.
*
* @since TopLink 10.1.3
*/
public class CMP3Policy extends CMPPolicy {
/** Stores the fields for this classes compound primary key class if required. */
protected transient KeyElementAccessor[] keyClassFields;
/** Used to look up the KeyElementAccessor for a specific DatabaseField, used for
resolving DerivedIds */
protected transient HashMap fieldToAccessorMap;
// Store the primary key class name
protected String pkClassName;
// Stores the class version of the PKClass
protected Class> pkClass = null;
public CMP3Policy() {
super();
}
/**
* INTERNAL:
* Add the read only mappings for the given field to the allMappings list.
*/
protected void addWritableMapping(ClassDescriptor aDescriptor, DatabaseField field, List allMappings) {
DatabaseMapping writableMapping = aDescriptor.getObjectBuilder().getMappingForField(field);
if (writableMapping != null) {
// Since it may be another aggregate mapping, add it to
// the allMappings list so we can drill down on it as
// well.
allMappings.add(writableMapping);
}
}
/**
* INTERNAL:
* Add the writable mapping for the given field to the allMappings list.
*/
protected void addReadOnlyMappings(ClassDescriptor aDescriptor, DatabaseField field, List allMappings) {
List readOnlyMappings = aDescriptor.getObjectBuilder().getReadOnlyMappingsForField(field);
if (readOnlyMappings != null) {
allMappings.addAll(readOnlyMappings);
}
}
/**
* INTERNAL:
* Clone the CMP3Policy
*/
@Override
public CMP3Policy clone() {
CMP3Policy policy = new CMP3Policy();
policy.setPrimaryKeyClassName(getPKClassName());
policy.setPKClass(getPKClass());
return policy;
}
/**
* INTERNAL:
* Convert all the class-name-based settings in this object to actual class-based
* settings. This method is used when converting a project that has been built
* with class names to a project with classes.
*/
@Override
public void convertClassNamesToClasses(ClassLoader classLoader){
if(getPKClassName() != null){
try{
Class> aPKClass = null;
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
try {
aPKClass = AccessController.doPrivileged(new PrivilegedClassForName<>(getPKClassName(), true, classLoader));
} catch (PrivilegedActionException exception) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("pk_class_not_found", new Object[] {this.pkClassName}), exception.getException());
}
} else {
aPKClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(getPKClassName(), true, classLoader);
}
setPKClass(aPKClass);
} catch (ClassNotFoundException exc){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("pk_class_not_found", new Object[] {this.pkClassName}), exc);
}
}
}
/**
* INTERNAL:
* Return if this policy is for CMP3.
*/
@Override
public boolean isCMP3Policy() {
return true;
}
/**
* INTERNAL:
*/
public void setPrimaryKeyClassName(String pkClassName) {
this.pkClassName = pkClassName;
}
/**
* INTERNAL:
* Return the java Class representing the primary key class name
*/
@Override
@SuppressWarnings({"unchecked"})
public Class getPKClass() {
return (Class) this.pkClass;
}
/**
* ADVANCED:
*/
public void setPKClass(Class> pkClass) {
this.pkClass = pkClass;
}
/**
* INTERNAL:
*/
public String getPKClassName() {
return pkClassName;
}
/**
* INTERNAL:
*/
@Override
public Object getPKClassInstance() {
try {
return getPKClass().getConstructor().newInstance();
} catch (ReflectiveOperationException ex) {
throw DescriptorException.exceptionAccessingPrimaryKeyInstance(this.getDescriptor(), ex);
}
}
/**
* INTERNAL:
* Use the key to create a EclipseLink primary key.
* If the key is simple (direct mapped) then just add it to a vector,
* otherwise must go through the inefficient process of copying the key into the bean
* and extracting the key from the bean.
*/
@Override
public Object createPrimaryKeyFromId(Object key, AbstractSession session) {
// If the descriptor primary key is mapped through direct-to-field mappings,
// then no elaborate conversion is required.
// If key is compound, add each value to the vector.
KeyElementAccessor[] pkElementArray = this.getKeyClassFields();
Object[] primaryKey = null;
if (getDescriptor().getCacheKeyType() != CacheKeyType.ID_VALUE) {
primaryKey = new Object[pkElementArray.length];
}
for (int index = 0; index < pkElementArray.length; index++) {
DatabaseMapping mapping = pkElementArray[index].getMapping();
Object fieldValue = null;
if (mapping.isAbstractColumnMapping()) {
if (pkElementArray[index].isNestedAccessor()) {
// We have nested aggregate(s) in the embedded id pkclass.
DatabaseField keyField = pkElementArray[index].getDatabaseField();
Object keyToUse = key;
DatabaseMapping keyMapping = getDescriptor().getObjectBuilder().getMappingForField(keyField);
if (keyMapping.isAggregateMapping()) {
keyMapping = keyMapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(keyField);
// Keep driving down the nested aggregates ...
while (keyMapping.isAggregateMapping()) {
keyToUse = keyMapping.getRealAttributeValueFromObject(keyToUse, session);
keyMapping = keyMapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(keyField);
}
fieldValue = ((AbstractColumnMapping)mapping).getFieldValue(pkElementArray[index].getValue(keyToUse, session), session);
} else {
// This should never hit but just in case ... better to get a proper exception rather than a NPE etc.
fieldValue = ((AbstractColumnMapping)mapping).getFieldValue(pkElementArray[index].getValue(keyToUse, session), session);
}
} else {
fieldValue = ((AbstractColumnMapping)mapping).getFieldValue(pkElementArray[index].getValue(key, session), session);
}
} else {
fieldValue = pkElementArray[index].getValue(key, session);
if ( (fieldValue !=null) && (pkClass != null) && (mapping.isOneToOneMapping()) ){
OneToOneMapping refmapping = (OneToOneMapping)mapping;
DatabaseField targetKey = refmapping.getSourceToTargetKeyFields().get(pkElementArray[index].getDatabaseField());
CMPPolicy refPolicy = refmapping.getReferenceDescriptor().getCMPPolicy();
if (refPolicy.isCMP3Policy()){
Class