diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationContext.java index dda2a32b601..b80bfc58aa6 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationContext.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationContext.java @@ -17,15 +17,25 @@ import javax.xml.namespace.QName; +import org.apache.commons.lang.BooleanUtils; + +import com.evolveum.midpoint.common.SynchronizationUtils; import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismProperty; import com.evolveum.midpoint.prism.util.PrismMonitor; import com.evolveum.midpoint.schema.constants.ObjectTypes; +import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.ConfigurationException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectSynchronizationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SynchronizationReactionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SynchronizationSituationType; @@ -33,6 +43,8 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; public class SynchronizationContext { + + private static final Trace LOGGER = TraceManager.getTrace(SynchronizationContext.class); private PrismObject applicableShadow; private PrismObject currentShadow; @@ -63,6 +75,50 @@ public SynchronizationContext(PrismObject applicableShadow, PrismObj this.result = result; } + public boolean isSynchronizationEnabled() { + if (objectSynchronization == null) { + return false; + } + return BooleanUtils.isNotFalse(objectSynchronization.isEnabled()); + } + + public boolean isProtected() { + if (applicableShadow == null) { + return false; + } + + ShadowType currentShadowType = applicableShadow.asObjectable(); + return BooleanUtils.isTrue(currentShadowType.isProtectedObject()); + } + + public boolean isSatisfyTaskConstraints() throws SchemaException { + + ShadowKindType kind = getTaskPropertyValue(SchemaConstants.MODEL_EXTENSION_KIND); + String intent = getTaskPropertyValue(SchemaConstants.MODEL_EXTENSION_INTENT); + QName objectClass = getTaskPropertyValue(SchemaConstants.MODEL_EXTENSION_OBJECTCLASS); + + LOGGER.trace("checking task constraints: {}", task); + + boolean isApplicable = SynchronizationUtils.isPolicyApplicable(objectClass, kind, intent, objectSynchronization, resource, true); + //this mean that kind/intent are null in the task..but this can be a case, so check if at least the objectClass is the same + if (!isApplicable && objectClass != null) { + return QNameUtil.matchAny(objectClass, objectSynchronization.getObjectClass()); + } + + return isApplicable; + } + + //TODO multi-threded tasks? + private T getTaskPropertyValue(QName propertyName) { + PrismProperty prop = task.getExtensionProperty(propertyName); + if (prop == null || prop.isEmpty()) { + return null; + } + + return prop.getRealValue(); + } + + public PrismObject getApplicableShadow() { return applicableShadow; } @@ -193,4 +249,5 @@ public boolean isForceIntentChange() { public void setForceIntentChange(boolean forceIntentChange) { this.forceIntentChange = forceIntentChange; } + } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationServiceImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationServiceImpl.java index 6bdc139b675..8b5bc0741f3 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationServiceImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationServiceImpl.java @@ -173,15 +173,15 @@ public void notifyChange(ResourceObjectShadowChangeDescrip ObjectSynchronizationType obejctSynchronization = syncCtx.getObjectSynchronization(); traceObjectSynchronization(obejctSynchronization); - if (!checkSynchronizationPolicy(syncCtx, eventInfo, task, subResult)) { + if (!checkSynchronizationPolicy(syncCtx, eventInfo)) { return; } - if (!checkTaskConstraints(syncCtx, eventInfo, task, subResult)) { + if (!checkTaskConstraints(syncCtx, eventInfo)) { return; } - if (!checkProtected(syncCtx, eventInfo, task, subResult)) { + if (!checkProtected(syncCtx, eventInfo)) { return; } @@ -190,22 +190,22 @@ public void notifyChange(ResourceObjectShadowChangeDescrip syncCtx.getFocusClass(), ModelImplUtils.getPolicyDesc(obejctSynchronization)); } - setupSituation(syncCtx, eventInfo, change, task, subResult); + setupSituation(syncCtx, eventInfo, change); - if (!checkDryRunAndUnrelatedChange(syncCtx, eventInfo, change, now, task, subResult)) { + if (!checkDryRunAndUnrelatedChange(syncCtx, eventInfo, change, now)) { return; } // must be here, because when the reaction has no action, the // situation won't be set. - PrismObject newCurrentShadow = saveSyncMetadata(syncCtx, change, now, task, parentResult); + PrismObject newCurrentShadow = saveSyncMetadata(syncCtx, change, now); if (newCurrentShadow != null) { change.setCurrentShadow(newCurrentShadow); syncCtx.setCurrentShadow(newCurrentShadow); } SynchronizationSituationType newSituation = reactToChange(syncCtx, change, - logDebug, task, subResult); + logDebug); eventInfo.setNewSituation(newSituation); eventInfo.record(task); subResult.computeStatus(); @@ -334,8 +334,10 @@ private void traceObjectSynchronization(ObjectSynchronizationType obejctSynchron } } - private boolean checkSynchronizationPolicy(SynchronizationContext syncCtx, SynchronizationEventInformation eventInfo, Task task, OperationResult subResult) { + private boolean checkSynchronizationPolicy(SynchronizationContext syncCtx, SynchronizationEventInformation eventInfo) { ObjectSynchronizationType obejctSynchronization = syncCtx.getObjectSynchronization(); + OperationResult subResult = syncCtx.getResult(); + Task task = syncCtx.getTask(); if (obejctSynchronization == null) { String message = "SYNCHRONIZATION no matching policy for " + syncCtx.getApplicableShadow() + " (" + syncCtx.getApplicableShadow().asObjectable().getObjectClass() + ") " + " on " + syncCtx.getResource() @@ -349,7 +351,7 @@ private boolean checkSynchronizationPolicy(Synchronization return false; } - if (!isSynchronizationEnabled(obejctSynchronization)) { + if (!syncCtx.isSynchronizationEnabled()) { String message = "SYNCHRONIZATION is not enabled for " + syncCtx.getResource() + " ignoring change from channel " + syncCtx.getChanel(); LOGGER.debug(message); @@ -364,13 +366,6 @@ private boolean checkSynchronizationPolicy(Synchronization return true; } - private boolean isSynchronizationEnabled(ObjectSynchronizationType synchronization) { - if (synchronization == null || synchronization.isEnabled() == null) { - return false; - } - return synchronization.isEnabled(); - } - /** * check if the kind/intent in the syncPolicy satisfy constraints defined in task * @param syncCtx @@ -380,8 +375,10 @@ private boolean isSynchronizationEnabled(ObjectSynchronizationType synchronizati * @return * @throws SchemaException */ - private boolean checkTaskConstraints(SynchronizationContext syncCtx, SynchronizationEventInformation eventInfo, Task task, OperationResult subResult) throws SchemaException { - if (!satisfyTaskConstraints(syncCtx)) { + private boolean checkTaskConstraints(SynchronizationContext syncCtx, SynchronizationEventInformation eventInfo) throws SchemaException { + if (!syncCtx.isSatisfyTaskConstraints()) { + OperationResult subResult = syncCtx.getResult(); + Task task = syncCtx.getTask(); LOGGER.trace("SYNCHRONIZATION skipping {} because it does not match kind/intent defined in task", new Object[] { syncCtx.getApplicableShadow() }); List> modifications = createShadowIntentAndSynchronizationTimestampDelta(syncCtx, @@ -397,34 +394,11 @@ private boolean checkTaskConstraints(SynchronizationContex return true; } - private boolean satisfyTaskConstraints(SynchronizationContext syncCtx) throws SchemaException { - - ShadowKindType kind = getPropertyValue(syncCtx.getTask(), SchemaConstants.MODEL_EXTENSION_KIND); - String intent = getPropertyValue(syncCtx.getTask(), SchemaConstants.MODEL_EXTENSION_INTENT); - QName objectClass = getPropertyValue(syncCtx.getTask(), SchemaConstants.MODEL_EXTENSION_OBJECTCLASS); - - LOGGER.trace("checking task constraints: {}", syncCtx.getTask()); - - boolean isApplicable = SynchronizationUtils.isPolicyApplicable(objectClass, kind, intent, syncCtx.getObjectSynchronization(), syncCtx.getResource(), true); - //this mean that kind/intent are null in the task..but this can be a case, so check if at least the objectClass is the same - if (!isApplicable && objectClass != null) { - return QNameUtil.matchAny(objectClass, syncCtx.getObjectSynchronization().getObjectClass()); - } - return isApplicable; - } - - private T getPropertyValue(Task task, QName propertyName) { - PrismProperty prop = task.getExtensionProperty(propertyName); - if (prop == null || prop.isEmpty()) { - return null; - } - - return prop.getRealValue(); - } - - private boolean checkProtected(SynchronizationContext syncCtx, SynchronizationEventInformation eventInfo, Task task, OperationResult subResult) { - if (isProtected(syncCtx.getApplicableShadow())) { + private boolean checkProtected(SynchronizationContext syncCtx, SynchronizationEventInformation eventInfo) { + if (syncCtx.isProtected()) { + OperationResult subResult = syncCtx.getResult(); + Task task = syncCtx.getTask(); List> modifications = createShadowIntentAndSynchronizationTimestampDelta(syncCtx, true); executeShadowModifications(syncCtx.getApplicableShadow(), modifications, task, subResult); subResult.recordSuccess(); @@ -436,21 +410,9 @@ private boolean checkProtected(SynchronizationContext s return true; } - private boolean isProtected(PrismObject shadow) { - if (shadow == null) { - return false; - } - - ShadowType currentShadowType = shadow.asObjectable(); - if (currentShadowType.isProtectedObject() == null) { - return false; - } - - return currentShadowType.isProtectedObject(); - } - - private boolean checkDryRunAndUnrelatedChange(SynchronizationContext syncCtx, SynchronizationEventInformation eventInfo, ResourceObjectShadowChangeDescription change, XMLGregorianCalendar now, Task task, OperationResult subResult) throws SchemaException { - + private boolean checkDryRunAndUnrelatedChange(SynchronizationContext syncCtx, SynchronizationEventInformation eventInfo, ResourceObjectShadowChangeDescription change, XMLGregorianCalendar now) throws SchemaException { + OperationResult subResult = syncCtx.getResult(); + Task task = syncCtx.getTask(); if (change.isUnrelatedChange() || ModelImplUtils.isDryRun(task)) { if (syncCtx.getApplicableShadow() == null) { throw new IllegalStateException("No current nor old shadow present: " + change); @@ -558,8 +520,10 @@ private void validate(ResourceObjectShadowChangeDescription change) { * {@link SynchronizationSituationType#DISPUTED} situation */ private void setupSituation(SynchronizationContext syncCtx, - SynchronizationEventInformation eventInfo, ResourceObjectShadowChangeDescription change, Task task, OperationResult result) { + SynchronizationEventInformation eventInfo, ResourceObjectShadowChangeDescription change) { + OperationResult result = syncCtx.getResult(); + Task task = syncCtx.getTask(); OperationResult subResult = result.createSubresult(CHECK_SITUATION); LOGGER.trace("Determining situation for resource object shadow."); @@ -814,8 +778,7 @@ private ChangeType getModificationType(ResourceObjectShadowChangeDescription cha } private SynchronizationSituationType reactToChange(SynchronizationContext syncCtx, - ResourceObjectShadowChangeDescription change, boolean logDebug, - Task task, OperationResult parentResult) + ResourceObjectShadowChangeDescription change, boolean logDebug) throws ConfigurationException, ObjectNotFoundException, SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException, CommunicationException, SecurityViolationException { @@ -855,6 +818,9 @@ private SynchronizationSituationType reactToChange(Synchro final boolean willSynchronize = isSynchronize(syncCtx.getReaction()); LensContext lensContext = null; + + OperationResult parentResult = syncCtx.getResult(); + Task task = syncCtx.getTask(); if (willSynchronize) { lensContext = createLensContext(syncCtx, change, syncCtx.getReaction(), options, parentResult); } @@ -1115,12 +1081,15 @@ private void findReactionDefinition(SynchronizationContext * Saves situation, timestamps, kind and intent (if needed) */ private PrismObject saveSyncMetadata(SynchronizationContext syncCtx, ResourceObjectShadowChangeDescription change, - XMLGregorianCalendar now, Task task, OperationResult parentResult) { + XMLGregorianCalendar now) { PrismObject shadow = syncCtx.getCurrentShadow(); if (shadow == null) { return null; } + OperationResult parentResult = syncCtx.getResult(); + Task task = syncCtx.getTask(); + try { ShadowType shadowType = shadow.asObjectable(); // new situation description