public synchronized Object findObject(Object id, boolean validate, boolean checkInheritance, String objectClassName)
{
assertIsOpen();
if (id == null)
{
throw new JPOXUserException(LOCALISER.msg("010044"));
}
// try to find object in cache(s)
Object pc = getObjectFromCache(id);
boolean fromCache = true;
ApiAdapter api = getApiAdapter();
if (id instanceof SCOID && pc != null)
{
if (api.isPersistent(pc) && !api.isNew(pc) && !api.isDeleted(pc) && !api.isTransactional(pc))
{
// JDO2 [5.4.4] Cant return HOLLOW nondurable objects
throw new JPOXUserException(LOCALISER.msg("010005"));
}
}
if (pc != null && api.isTransactional(pc))
{
// 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 JPOXUserException(LOCALISER.msg("010006"));
}
else if (id instanceof OID)
{
// OID, so check that the implied class is managed
originalClassName = getStoreManager().manageClassForIdentity(id, getClassLoaderResolver());
}
else if (api.isSingleFieldIdentity(id))
{
// SingleFieldIdentity, so check that the implied class is managed
originalClassName = getStoreManager().manageClassForIdentity(id, getClassLoaderResolver());
}
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 JPOXObjectNotFoundException(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 (id instanceof OID)
{
// Create new OID using correct target class
id = OIDFactory.getInstance(this, className, ((OID)id).getKeyValue());
// try again to read object from cache with this id
pc = getObjectFromCache(id);
}
else if (api.isSingleFieldIdentity(id))
{
// Create new SingleFieldIdentity using correct targetClass
id = api.getNewSingleFieldIdentity(id.getClass(), getClassLoaderResolver().classForName(className),
api.getTargetKeyForSingleFieldIdentity(id));
// try again to read object from cache with this id
pc = getObjectFromCache(id);
}
}
}
else
{
className = originalClassName;
}
if (pc == null)
{
// Still not found so create a Hollow instance with the supplied field values
try
{
Class pcClass = clr.classForName(className, (id instanceof OID) ? null : id.getClass().getClassLoader());
sm = StateManagerFactory.newStateManagerForHollow(this, pcClass, id);
pc = sm.getObject();
fromCache = false;
}
catch (ClassNotResolvedException e)
{
JPOXLogger.PERSISTENCE.warn(LOCALISER.msg("010027", id));
throw new JPOXUserException(LOCALISER.msg("010027", id), e);
}
}
}
}