use of org.datanucleus.exceptions.NucleusUserException in project datanucleus-core by datanucleus.
the class StateManagerImpl method detachCopy.
/**
* Method to make detached copy of this instance
* If the object is detachable then the copy will be migrated to DETACHED state, otherwise will migrate
* the copy to TRANSIENT. Used by "ExecutionContext.detachObjectCopy()".
* @param state State for the detachment process
* @return the detached Persistable instance
*/
public Persistable detachCopy(FetchPlanState state) {
if (myLC.isDeleted()) {
throw new NucleusUserException(Localiser.msg("026023", myPC.getClass().getName(), myID));
}
if (myEC.getApiAdapter().isDetached(myPC)) {
throw new NucleusUserException(Localiser.msg("026024", myPC.getClass().getName(), myID));
}
if (dirty) {
myEC.flushInternal(false);
}
if (isDetaching()) {
// Object in the process of detaching (recursive) so return the object which will be the detached object
return getReferencedPC();
}
// Look for an existing detached copy
DetachState detachState = (DetachState) state;
DetachState.Entry existingDetached = detachState.getDetachedCopyEntry(myPC);
Persistable detachedPC;
if (existingDetached == null) {
// No existing detached copy - create new one
detachedPC = myPC.dnNewInstance(this);
detachState.setDetachedCopyEntry(myPC, detachedPC);
} else {
// Found one - if it's sufficient for current FetchPlanState, return it immediately
detachedPC = (Persistable) existingDetached.getDetachedCopyObject();
if (existingDetached.checkCurrentState()) {
return detachedPC;
}
// Need to process the detached copy using current FetchPlanState
}
myEC.setAttachDetachReferencedObject(this, detachedPC);
// Check if detachable ... if so then we detach a copy, otherwise we return a transient copy
boolean detachable = myEC.getApiAdapter().isDetachable(myPC);
// make sure a detaching PC is not read by another thread while we are detaching
Object referencedPC = getReferencedPC();
synchronized (referencedPC) {
int[] detachFieldNums = getFieldsNumbersToDetach();
if (detachable) {
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
int[] fieldsToLoad = null;
if ((myEC.getFetchPlan().getDetachmentOptions() & FetchPlan.DETACH_LOAD_FIELDS) != 0) {
fieldsToLoad = ClassUtils.getFlagsSetTo(loadedFields, myFP.getMemberNumbers(), false);
}
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010010", StringUtils.toJVMIDString(myPC), "" + state.getCurrentFetchDepth(), StringUtils.toJVMIDString(detachedPC), StringUtils.intArrayToString(detachFieldNums), StringUtils.intArrayToString(fieldsToLoad)));
}
// Call any "pre-detach" listeners
getCallbackHandler().preDetach(myPC);
}
try {
setDetaching(true);
// Handle any field loading/unloading before the detach
if ((myEC.getFetchPlan().getDetachmentOptions() & FetchPlan.DETACH_LOAD_FIELDS) != 0) {
// Load any unloaded fetch-plan fields
loadUnloadedFieldsInFetchPlan();
}
if (myLC == myEC.getNucleusContext().getApiAdapter().getLifeCycleState(LifeCycleState.HOLLOW) || myLC == myEC.getNucleusContext().getApiAdapter().getLifeCycleState(LifeCycleState.P_NONTRANS)) {
// Migrate any HOLLOW/P_NONTRANS to P_CLEAN etc
myLC = myLC.transitionReadField(this, true);
}
// Create a SM for our copy object
ObjectProvider smDetachedPC = new StateManagerImpl(myEC, cmd);
smDetachedPC.initialiseForDetached(detachedPC, getExternalObjectId(myPC), getVersion(myPC));
myEC.setAttachDetachReferencedObject(smDetachedPC, myPC);
// If detached copy already existed, take note of fields previously loaded
if (existingDetached != null) {
smDetachedPC.retrieveDetachState(smDetachedPC);
}
smDetachedPC.replaceFields(detachFieldNums, new DetachFieldManager(this, cmd.getSCOMutableMemberFlags(), myFP, state, true));
myEC.setAttachDetachReferencedObject(smDetachedPC, null);
if (detachable) {
// Update the object with its detached state - not to be confused with the "state" object above
detachedPC.dnReplaceFlags();
((Detachable) detachedPC).dnReplaceDetachedState();
} else {
smDetachedPC.makeTransient(null);
}
// Remove its StateManager since now detached or transient
replaceStateManager(detachedPC, null);
} catch (Exception e) {
// What could possibly be wrong here ? Log it and let the user provide a testcase, yeah right
NucleusLogger.PERSISTENCE.warn("DETACH ERROR : Error thrown while detaching " + StringUtils.toJVMIDString(myPC) + " (id=" + myID + "). Provide a testcase that demonstrates this", e);
} finally {
setDetaching(false);
referencedPC = null;
}
if (detachable && !myEC.getApiAdapter().isDetached(detachedPC)) {
// Sanity check on the objects detached state
throw new NucleusUserException(Localiser.msg("026025", detachedPC.getClass().getName(), myID));
}
if (detachable) {
// Call any "post-detach" listeners
getCallbackHandler().postDetach(myPC, detachedPC);
}
}
return detachedPC;
}
use of org.datanucleus.exceptions.NucleusUserException in project datanucleus-core by datanucleus.
the class StateManagerImpl method checkInheritance.
/**
* Look to the database to determine which class this object is. This parameter is a hint. Set false, if it's
* already determined the correct pcClass for this pc "object" in a certain
* level in the hierarchy. Set to true and it will look to the database.
* TODO This is only called by some outdated code in LDAPUtils; remove it when that is fixed
* @param fv the initial field values of the object.
* @deprecated Dont use this, to be removed
*/
public void checkInheritance(FieldValues fv) {
// Inheritance case, check the level of the instance
ClassLoaderResolver clr = myEC.getClassLoaderResolver();
String className = getStoreManager().getClassNameForObjectID(myID, clr, myEC);
if (className == null) {
// className is null when id class exists, and object has been validated and doesn't exist.
throw new NucleusObjectNotFoundException(Localiser.msg("026013", IdentityUtils.getPersistableIdentityForId(myID)), myID);
} else if (!cmd.getFullClassName().equals(className)) {
Class pcClass;
try {
// load the class and make sure the class is initialized
pcClass = clr.classForName(className, myID.getClass().getClassLoader(), true);
cmd = myEC.getMetaDataManager().getMetaDataForClass(pcClass, clr);
} catch (ClassNotResolvedException e) {
NucleusLogger.PERSISTENCE.warn(Localiser.msg("026014", IdentityUtils.getPersistableIdentityForId(myID)));
throw new NucleusUserException(Localiser.msg("026014", IdentityUtils.getPersistableIdentityForId(myID)), e);
}
if (cmd == null) {
throw new NucleusUserException(Localiser.msg("026012", pcClass)).setFatal();
}
if (cmd.getIdentityType() != IdentityType.APPLICATION) {
throw new NucleusUserException("This method should only be used for objects using application identity.").setFatal();
}
myFP = myEC.getFetchPlan().getFetchPlanForClass(cmd);
int fieldCount = cmd.getMemberCount();
dirtyFields = new boolean[fieldCount];
loadedFields = new boolean[fieldCount];
// Create new PC at right inheritance level
myPC = HELPER.newInstance(pcClass, this);
if (myPC == null) {
throw new NucleusUserException(Localiser.msg("026018", cmd.getFullClassName())).setFatal();
}
// Note that this will mean the fields are loaded twice (loaded earlier in this method)
// and also that postLoad will be called twice
loadFieldValues(fv);
// Create the id for the new PC
myID = myEC.getNucleusContext().getIdentityManager().getApplicationId(myPC, cmd);
}
}
use of org.datanucleus.exceptions.NucleusUserException in project datanucleus-core by datanucleus.
the class AbstractStoreManager method getValueGenerationStrategyForNative.
/**
* Method defining which value-strategy to use when the user specifies "native". This will return as follows
* <ul>
* <li>If your field is Numeric-based (or datastore-id with numeric or no jdbc-type) then chooses the
* first one that is supported of "identity", "sequence", "increment", otherwise exception.</li>
* <li>Otherwise your field is String-based then chooses "uuid-hex".</li>
* </ul>
* If your store plugin requires something else then override this
* @param cmd Class requiring the strategy
* @param absFieldNumber Field of the class
* @return The strategy used when "native" is specified
*/
public String getValueGenerationStrategyForNative(AbstractClassMetaData cmd, int absFieldNumber) {
if (absFieldNumber >= 0) {
AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(absFieldNumber);
Class type = mmd.getType();
if (String.class.isAssignableFrom(type)) {
// TODO Do we really want this when we have "uuid"?
return ValueGenerationStrategy.UUIDHEX.toString();
} else if (type == Long.class || type == Integer.class || type == Short.class || type == long.class || type == int.class || type == short.class || type == BigInteger.class) {
if (supportsValueGenerationStrategy(ValueGenerationStrategy.IDENTITY.toString())) {
return ValueGenerationStrategy.IDENTITY.toString();
} else if (supportsValueGenerationStrategy(ValueGenerationStrategy.SEQUENCE.toString()) && mmd.getSequence() != null) {
return ValueGenerationStrategy.SEQUENCE.toString();
} else if (supportsValueGenerationStrategy(ValueGenerationStrategy.INCREMENT.toString())) {
return ValueGenerationStrategy.INCREMENT.toString();
}
throw new NucleusUserException("This datastore provider doesn't support numeric native strategy for member " + mmd.getFullFieldName());
} else {
throw new NucleusUserException("This datastore provider doesn't support native strategy for field of type " + type.getName());
}
}
IdentityMetaData idmd = cmd.getBaseIdentityMetaData();
if (idmd != null && idmd.getColumnMetaData() != null) {
if (MetaDataUtils.isJdbcTypeString(idmd.getColumnMetaData().getJdbcType())) {
return ValueGenerationStrategy.UUIDHEX.toString();
}
}
// Numeric datastore-identity
if (supportsValueGenerationStrategy(ValueGenerationStrategy.IDENTITY.toString())) {
return ValueGenerationStrategy.IDENTITY.toString();
} else if (supportsValueGenerationStrategy(ValueGenerationStrategy.SEQUENCE.toString()) && idmd != null && idmd.getSequence() != null) {
return ValueGenerationStrategy.SEQUENCE.toString();
} else if (supportsValueGenerationStrategy(ValueGenerationStrategy.INCREMENT.toString())) {
return ValueGenerationStrategy.INCREMENT.toString();
}
throw new NucleusUserException("This datastore provider doesn't support numeric native strategy for class " + cmd.getFullClassName());
}
use of org.datanucleus.exceptions.NucleusUserException in project datanucleus-core by datanucleus.
the class AbstractStoreManager method getValueGeneratorForMember.
protected synchronized ValueGenerator getValueGeneratorForMember(ClassLoaderResolver clr, AbstractClassMetaData cmd, int absoluteFieldNumber) {
String memberKey = valueGenerationMgr.getMemberKey(cmd, absoluteFieldNumber);
// Check if we have a ValueGenerator already created for this member
ValueGenerator generator = valueGenerationMgr.getValueGeneratorForMemberKey(memberKey);
if (generator != null) {
// Return the ValueGenerator already registered against this member "key"
return generator;
}
// No ValueGenerator registered for this memberKey, so need to determine which to use and create it as required.
String fieldName = null;
ValueGenerationStrategy strategy = null;
String sequence = null;
String valueGeneratorName = null;
if (absoluteFieldNumber >= 0) {
// real field
AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(absoluteFieldNumber);
fieldName = mmd.getFullFieldName();
strategy = mmd.getValueStrategy();
sequence = mmd.getSequence();
valueGeneratorName = mmd.getValueGeneratorName();
} else {
// datastore-identity surrogate field
fieldName = cmd.getFullClassName() + " (datastore id)";
strategy = cmd.getIdentityMetaData().getValueStrategy();
sequence = cmd.getIdentityMetaData().getSequence();
valueGeneratorName = cmd.getIdentityMetaData().getValueGeneratorName();
}
String strategyName = strategy.toString();
if (strategy.equals(ValueGenerationStrategy.CUSTOM)) {
// Using a "custom" generator
strategyName = strategy.getCustomName();
} else if (strategy.equals(ValueGenerationStrategy.NATIVE)) {
strategyName = getValueGenerationStrategyForNative(cmd, absoluteFieldNumber);
strategy = ValueGenerationStrategy.getIdentityStrategy(strategyName);
}
// Check for this strategy being a "unique" ValueGenerator, and created if not yet present
generator = valueGenerationMgr.getUniqueValueGeneratorByName(strategyName);
if (generator != null) {
// "unique" ValueGenerator already defined for this strategy, so register it against the member
valueGenerationMgr.registerValueGeneratorForMemberKey(memberKey, generator);
return generator;
}
// Must be "datastore" specific generator so use plugin mechanism to create one and register against this member "key"
// Set up the default properties available for all value generators
// Extract any metadata-based generation information keyed by the "valueGeneratorName"
TableGeneratorMetaData tableGeneratorMetaData = null;
SequenceMetaData sequenceMetaData = null;
if (valueGeneratorName != null) {
if (strategy == ValueGenerationStrategy.INCREMENT) {
tableGeneratorMetaData = getMetaDataManager().getMetaDataForTableGenerator(clr, valueGeneratorName);
if (tableGeneratorMetaData == null) {
throw new NucleusUserException(Localiser.msg("038005", fieldName, valueGeneratorName));
}
} else if (strategy == ValueGenerationStrategy.SEQUENCE) {
sequenceMetaData = getMetaDataManager().getMetaDataForSequence(clr, valueGeneratorName);
if (sequenceMetaData == null) {
throw new NucleusUserException(Localiser.msg("038006", fieldName, valueGeneratorName));
}
}
} else if (strategy == ValueGenerationStrategy.SEQUENCE && sequence != null) {
// TODO Allow for package name of this class prefix for the sequence name
sequenceMetaData = getMetaDataManager().getMetaDataForSequence(clr, sequence);
if (sequenceMetaData == null) {
// No <sequence> defining the datastore sequence name, so fallback to this name directly in the datastore
NucleusLogger.VALUEGENERATION.info("Member " + fieldName + " has been specified to use sequence '" + sequence + "' but there is no <sequence> specified in the MetaData. Falling back to use a sequence in the datastore with this name directly.");
}
}
Properties props = getPropertiesForValueGenerator(cmd, absoluteFieldNumber, clr, sequenceMetaData, tableGeneratorMetaData);
return valueGenerationMgr.createAndRegisterValueGenerator(memberKey, strategyName, props);
}
use of org.datanucleus.exceptions.NucleusUserException in project datanucleus-core by datanucleus.
the class TemporalMonthJavaMethod method evaluate.
/* (non-Javadoc)
* @see org.datanucleus.query.evaluator.memory.InvocationEvaluator#evaluate(org.datanucleus.query.expression.InvokeExpression, org.datanucleus.query.evaluator.memory.InMemoryExpressionEvaluator)
*/
public Object evaluate(InvokeExpression expr, Object invokedValue, InMemoryExpressionEvaluator eval) {
if (invokedValue == null && expr.getArguments() != null) {
// Specified as static function, so use argument of InvokeExpression
List<Expression> argExprs = expr.getArguments();
if (argExprs.size() > 1) {
throw new NucleusUserException("Incorrect number of arguments to MONTH_JAVA");
}
Expression argExpr = argExprs.get(0);
invokedValue = eval.getValueForExpression(argExpr);
}
if (invokedValue == null) {
return Boolean.FALSE;
}
if (!(invokedValue instanceof Date)) {
throw new NucleusException(Localiser.msg("021011", expr.getOperation(), invokedValue.getClass().getName()));
}
if (invokedValue instanceof Date) {
Calendar cal = Calendar.getInstance();
cal.setTime((Date) invokedValue);
return Integer.valueOf(cal.get(Calendar.MONTH));
} else if (invokedValue instanceof Calendar) {
return Integer.valueOf(((Calendar) invokedValue).get(Calendar.MONTH));
} else if (invokedValue instanceof LocalDate) {
return ((LocalDate) invokedValue).getMonthValue() - 1;
} else if (invokedValue instanceof LocalDateTime) {
return ((LocalDateTime) invokedValue).getMonthValue() - 1;
} else {
throw new NucleusUserException("We do not currently support MONTH_JAVA() with argument of type " + invokedValue.getClass().getName());
}
}
Aggregations