Skip to content

Commit

Permalink
Consistency update, part 3. Work in progress.
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Jul 18, 2018
1 parent ed442ff commit cf6a600
Show file tree
Hide file tree
Showing 12 changed files with 647 additions and 89 deletions.
Expand Up @@ -717,6 +717,11 @@ public static void assertEqualsPolyString(String message, PolyStringType expecte
assert MiscUtil.equals(expected.getOrig(), actual.getOrig()) : message+"; expected orig '"+expected.getOrig()+ "' but was '" + actual.getOrig() + "'";
assert MiscUtil.equals(expected.getNorm(), actual.getNorm()) : message+"; expected norm '"+expected.getNorm()+ "' but was '" + actual.getNorm() + "'";
}

public static void assertMatchesQName(String message, QName expected, QName actual) {
assert actual != null : message + ": null value";
assert QNameUtil.match(expected, actual) : message+"; expected "+expected+ " but was " + actual;
}

// Calendar asserts

Expand Down
Expand Up @@ -498,9 +498,16 @@ public static boolean isProtected(PrismObject<? extends ShadowType> shadow) {
return (protectedObject != null && protectedObject);
}

public static boolean isDead(ShadowType shadow){
return shadow.isDead() != null && shadow.isDead();
public static boolean isDead(ShadowType shadow) {
Boolean dead = shadow.isDead();
return dead != null && dead;
}

public static boolean isExists(ShadowType shadow) {
Boolean exists = shadow.isExists();
return exists == null || exists;
}


public static boolean matches(ShadowType shadowType, String resourceOid, ShadowKindType kind, String intent) {
if (shadowType == null) {
Expand Down Expand Up @@ -753,7 +760,7 @@ private static <T> void validateAttribute(ResourceAttribute<T> attribute,
if (val == null) {
throw new SchemaException("Null value in attribute "+attrName);
}
LOGGER.info("MMMMMMMMMMMM: {}:{}\n {} <-> {}", attrName, attrDef, expectedClass, val.getClass());
// LOGGER.info("MMMMMMMMMMMM: {}:{}\n {} <-> {}", attrName, attrDef, expectedClass, val.getClass());
if (!XmlTypeConverter.isMatchingType(expectedClass, val.getClass())) {
throw new SchemaException("Wrong value in attribute "+attrName+"; expected class "+attrDef.getTypeClass().getSimpleName()+", but was "+val.getClass());
}
Expand Down
Expand Up @@ -103,6 +103,10 @@ public boolean isExecuting() {
return executionStatus == PendingOperationExecutionStatusType.EXECUTING;
}

public boolean isSuccess() {
return OperationResultStatusType.SUCCESS.equals(getResultStatusType());
}


public OperationResultStatusType getResultStatusType() {
OperationResultStatus resultStatus = getResultStatus();
Expand Down
Expand Up @@ -587,11 +587,10 @@ private String addShadowAttempt(ProvisioningContext ctx,
// This is where the repo shadow is created or updated (if needed)
shadowManager.recordAddResult(ctx, shadowToAdd, opState, parentResult);

if (addedShadow != null) {
addedShadow.setOid(opState.getRepoShadow().getOid());
} else {
if (addedShadow == null) {
addedShadow = shadowToAdd;
}
addedShadow.setOid(opState.getRepoShadow().getOid());

notifyAfterAdd(ctx, addedShadow, opState, task, parentResult);

Expand Down
Expand Up @@ -823,50 +823,6 @@ public void recordAddResult(
}
}

/**
* Record results of an operation that have thrown exception.
* This happens after the error handler is processed - and only for those
* cases when the handler has re-thrown the exception.
*/
public void recordOperationException(
ProvisioningContext ctx,
ProvisioningOperationState<AsynchronousOperationReturnValue<PrismObject<ShadowType>>> opState,
ObjectDelta<ShadowType> delta,
OperationResult parentResult)
throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ObjectAlreadyExistsException, ExpressionEvaluationException {
PrismObject<ShadowType> repoShadow = opState.getRepoShadow();
if (repoShadow == null) {
// Shadow does not exist. As this operation immediately ends up with an error then
// we not even bother to create a shadow.
return;
}

Collection<ItemDelta> shadowChanges = new ArrayList<>();

if (opState.hasPendingOperations()) {
collectPendingOperationUpdates(shadowChanges, opState, OperationResultStatus.FATAL_ERROR);
}

if (delta.isAdd()) {
// This means we have failed add operation here. We tried to add object,
// but we have failed. Which means that this shadow is now dead.
PrismPropertyDefinition<Boolean> deadDef = repoShadow.getDefinition().findPropertyDefinition(ShadowType.F_DEAD);
PropertyDelta<Boolean> deadDelta = deadDef.createEmptyDelta(new ItemPath(ShadowType.F_DEAD));
deadDelta.setValuesToReplace(new PrismPropertyValue<>(Boolean.TRUE));
shadowChanges.add(deadDelta);
}

if (shadowChanges.isEmpty()) {
return;
}

if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Updading repository shadow (after error handling)\n{}", DebugUtil.debugDump(shadowChanges, 1));
}

repositoryService.modifyObject(ShadowType.class, opState.getRepoShadow().getOid(), shadowChanges, parentResult);
}

/**
* Add new active shadow to repository. It is executed after ADD operation on resource.
* There are several scenarios. The operation may have been executed (synchronous operation),
Expand Down Expand Up @@ -940,14 +896,7 @@ private void recordAddResultExistingShadow(
resourceShadow = opState.getAsyncResult().getReturnValue();
}

PrismObject<ShadowType> proposedShadow = repositoryService.getObject(ShadowType.class, opState.getRepoShadow().getOid(), null, parentResult);

if (proposedShadow == null) {
parentResult
.recordFatalError("Error while creating account shadow object to save in the reposiotory. Proposed shadow is gone.");
throw new IllegalStateException(
"Error while creating account shadow object to save in the reposiotory. Proposed shadow is gone.");
}
PrismObject<ShadowType> repoShadow = opState.getRepoShadow();

Collection<ItemDelta> shadowChanges = new ArrayList<>();

Expand All @@ -959,7 +908,7 @@ private void recordAddResultExistingShadow(

if (!opState.isCompleted()) {

PrismContainerDefinition<PendingOperationType> containerDefinition = proposedShadow.getDefinition().findContainerDefinition(ShadowType.F_PENDING_OPERATION);
PrismContainerDefinition<PendingOperationType> containerDefinition = repoShadow.getDefinition().findContainerDefinition(ShadowType.F_PENDING_OPERATION);
ContainerDelta<PendingOperationType> pendingOperationDelta =containerDefinition.createEmptyDelta(new ItemPath(ShadowType.F_PENDING_OPERATION));
PendingOperationType pendingOperation = createPendingOperationAdd(resourceShadow, opState, null);
pendingOperationDelta.addValuesToAdd(pendingOperation.asPrismContainerValue());
Expand All @@ -969,24 +918,83 @@ private void recordAddResultExistingShadow(
}
}

PrismPropertyDefinition<String> lifecycleDef = proposedShadow.getDefinition().findPropertyDefinition(ShadowType.F_LIFECYCLE_STATE);
PropertyDelta<String> lifecycleDelta = lifecycleDef.createEmptyDelta(new ItemPath(ShadowType.F_LIFECYCLE_STATE));
lifecycleDelta.setValuesToReplace(new PrismPropertyValue<>(SchemaConstants.LIFECYCLE_ACTIVE));
shadowChanges.add(lifecycleDelta);
if (opState.isCompleted() && opState.isSuccess() && !ShadowUtil.isExists(repoShadow.asObjectable())) {
shadowChanges.add(createShadowPropertyReplaceDelta(repoShadow, ShadowType.F_EXISTS, null));
}

String currentLifecycleState = repoShadow.asObjectable().getLifecycleState();
if (currentLifecycleState != null && !currentLifecycleState.equals(SchemaConstants.LIFECYCLE_ACTIVE)) {
shadowChanges.add(createShadowPropertyReplaceDelta(repoShadow, ShadowType.F_LIFECYCLE_STATE, SchemaConstants.LIFECYCLE_ACTIVE));
}

computeUpdateShadowAttributeChanges(ctx, shadowChanges, resourceShadow, proposedShadow);
computeUpdateShadowAttributeChanges(ctx, shadowChanges, resourceShadow, repoShadow);

if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Updading repository shadow\n{}", DebugUtil.debugDump(shadowChanges, 1));
}

repositoryService.modifyObject(ShadowType.class, proposedShadow.getOid(), shadowChanges, parentResult);
repositoryService.modifyObject(ShadowType.class, repoShadow.getOid(), shadowChanges, parentResult);

LOGGER.trace("Repository shadow updated");

parentResult.recordSuccess();
}

private <T> PropertyDelta<T> createShadowPropertyReplaceDelta(PrismObject<ShadowType> repoShadow, QName propName, T value) {
PrismPropertyDefinition<T> def = repoShadow.getDefinition().findPropertyDefinition(propName);
PropertyDelta<T> delta = def.createEmptyDelta(new ItemPath(propName));
if (value == null) {
delta.setValueToReplace();
} else {
delta.setValuesToReplace(new PrismPropertyValue<>(value));
}
return delta;
}

/**
* Record results of an operation that have thrown exception.
* This happens after the error handler is processed - and only for those
* cases when the handler has re-thrown the exception.
*/
public void recordOperationException(
ProvisioningContext ctx,
ProvisioningOperationState<AsynchronousOperationReturnValue<PrismObject<ShadowType>>> opState,
ObjectDelta<ShadowType> delta,
OperationResult parentResult)
throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ObjectAlreadyExistsException, ExpressionEvaluationException {
PrismObject<ShadowType> repoShadow = opState.getRepoShadow();
if (repoShadow == null) {
// Shadow does not exist. As this operation immediately ends up with an error then
// we not even bother to create a shadow.
return;
}

Collection<ItemDelta> shadowChanges = new ArrayList<>();

if (opState.hasPendingOperations()) {
collectPendingOperationUpdates(shadowChanges, opState, OperationResultStatus.FATAL_ERROR);
}

if (delta.isAdd()) {
// This means we have failed add operation here. We tried to add object,
// but we have failed. Which means that this shadow is now dead.
PrismPropertyDefinition<Boolean> deadDef = repoShadow.getDefinition().findPropertyDefinition(ShadowType.F_DEAD);
PropertyDelta<Boolean> deadDelta = deadDef.createEmptyDelta(new ItemPath(ShadowType.F_DEAD));
deadDelta.setValuesToReplace(new PrismPropertyValue<>(Boolean.TRUE));
shadowChanges.add(deadDelta);
}

if (shadowChanges.isEmpty()) {
return;
}

if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Updading repository shadow (after error handling)\n{}", DebugUtil.debugDump(shadowChanges, 1));
}

repositoryService.modifyObject(ShadowType.class, opState.getRepoShadow().getOid(), shadowChanges, parentResult);
}

private void collectPendingOperationUpdates(Collection<ItemDelta> shadowChanges,
ProvisioningOperationState<AsynchronousOperationReturnValue<PrismObject<ShadowType>>> opState, OperationResultStatus implicitStatus) {

Expand Down

0 comments on commit cf6a600

Please sign in to comment.