{
// JDO2 [12.6.5] If there's already an object with the same id and it's transactional, return it
return pc;
}
StateManager sm = null;
if (pc == null)
{
// Find it direct from the store if the store supports that
pc = getStoreManager().getPersistenceHandler().findObject(this, id);
if (pc == null)
{
// Object not found in cache(s) with this identity
String className = null;
String originalClassName = null;
boolean checkedClassName = false;
if (id instanceof SCOID)
{
throw new NucleusUserException(LOCALISER.msg("010006"));
}
else if (id instanceof DatastoreUniqueOID)
{
throw new NucleusObjectNotFoundException(LOCALISER.msg("010026"), id);
}
else if (api.isDatastoreIdentity(id) || api.isSingleFieldIdentity(id))
{
// DatastoreIdentity or SingleFieldIdentity, so check that the implied class is managed
originalClassName = getStoreManager().manageClassForIdentity(id, clr);
}
else if (objectClassName != null)
{
// Object class name specified so use that directly
originalClassName = objectClassName;
}
else
{
// We dont know the object class so try to deduce it from what is known by the StoreManager
originalClassName = getStoreManager().getClassNameForObjectID(id, clr, this);
checkedClassName = true;
}
if (checkInheritance)
{
// Verify if correct class inheritance level is set
if (!checkedClassName)
{
className = getStoreManager().getClassNameForObjectID(id, clr, this);
}
else
{
// We just checked the name of the class in the section above so just use that
className = originalClassName;
}
if (className == null)
{
throw new NucleusObjectNotFoundException(LOCALISER.msg("010026"), id);
}
if (originalClassName != null && !originalClassName.equals(className))
{
// Inheritance checking has found a different inherited
// object with this identity so create new id
if (api.isDatastoreIdentity(id))
{
// Create new OID using correct target class and recheck the cache
id = OIDFactory.getInstance(getNucleusContext(), className, ((OID)id).getKeyValue());
pc = getObjectFromCache(id);
}
else if (api.isSingleFieldIdentity(id))
{
// Create new SingleFieldIdentity using correct targetClass and recheck the cache
id = api.getNewSingleFieldIdentity(id.getClass(), clr.classForName(className),
api.getTargetKeyForSingleFieldIdentity(id));
pc = getObjectFromCache(id);
}
}
}
else
{
className = originalClassName;
}
if (pc == null)
{
// Still not found, so create a Hollow instance with supplied PK values if possible
try
{
Class pcClass = clr.classForName(className, (id instanceof OID) ? null : id.getClass().getClassLoader());
if (Modifier.isAbstract(pcClass.getModifiers()))
{
// This class is abstract so impossible to have an instance of this type
throw new NucleusObjectNotFoundException(LOCALISER.msg("010027",
getIdentityAsString(id), className));
}
sm = (StateManager) ObjectProviderFactory.newForHollow(this, pcClass, id);
pc = sm.getObject();
fromCache = false;
if (!checkInheritance && !validate)
{
// Mark the StateManager as needing to validate this object before loading fields
sm.markForInheritanceValidation();
}
}
catch (ClassNotResolvedException e)
{
NucleusLogger.PERSISTENCE.warn(LOCALISER.msg("010027", getIdentityAsString(id)));
throw new NucleusUserException(LOCALISER.msg("010027", getIdentityAsString(id)), e);
}
}
}
}
// TODO If we have serializeReadObjects set and in pessimistic txn and get the object from the cache
// we need to apply a lock here
boolean performValidationWhenCached = (context.getPersistenceConfiguration().getBooleanProperty("datanucleus.findObject.validateWhenCached"));
if (validate && (!fromCache || performValidationWhenCached))
{
// User requests validation of the instance so go to the datastore to validate it
// loading any fetchplan fields that are needed in the process.
if (sm == null)
{
sm = findStateManager(pc);
}
if (sm != null && !fromCache)
{
// Cache the object in case we have bidirectional relations that would need to find this
putObjectIntoCache(sm);
}
try
{
sm.validate();
}
catch (NucleusObjectNotFoundException onfe)
{
// Object doesn't exist, so remove from L1 cache
removeObjectFromCache(sm.getInternalObjectId());
throw onfe;
}
if (sm.getObject() != pc)
{
// Underlying object was changed in the validation process. This can happen when the datastore
// is responsible for managing object references and it no longer recognises the cached value.
fromCache = false;
removeObjectFromCache(sm.getInternalObjectId());
}
if (!fromCache)
{
// We created a Hollow PC earlier but then went to the datastore and let it find the real object
// This allows the datastore to replace this temporary Hollow object with the real datastore object if required
// This doesnt change with RDBMS datastores since we just pull in fields, but for DB4O we pull in object graphs
pc = sm.getObject();
}
}
if (sm != null && !fromCache)
{