Skip to content

Commit

Permalink
small cleanup for synchronization service
Browse files Browse the repository at this point in the history
  • Loading branch information
katkav committed Sep 13, 2018
1 parent 50036c7 commit 59956c9
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 64 deletions.
Expand Up @@ -17,22 +17,34 @@

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;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;

public class SynchronizationContext<F extends FocusType> {

private static final Trace LOGGER = TraceManager.getTrace(SynchronizationContext.class);

private PrismObject<ShadowType> applicableShadow;
private PrismObject<ShadowType> currentShadow;
Expand Down Expand Up @@ -63,6 +75,50 @@ public SynchronizationContext(PrismObject<ShadowType> 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> T getTaskPropertyValue(QName propertyName) {
PrismProperty<T> prop = task.getExtensionProperty(propertyName);
if (prop == null || prop.isEmpty()) {
return null;
}

return prop.getRealValue();
}


public PrismObject<ShadowType> getApplicableShadow() {
return applicableShadow;
}
Expand Down Expand Up @@ -193,4 +249,5 @@ public boolean isForceIntentChange() {
public void setForceIntentChange(boolean forceIntentChange) {
this.forceIntentChange = forceIntentChange;
}

}
Expand Up @@ -173,15 +173,15 @@ public <F extends FocusType> 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;
}

Expand All @@ -190,22 +190,22 @@ public <F extends FocusType> 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<ShadowType> newCurrentShadow = saveSyncMetadata(syncCtx, change, now, task, parentResult);
PrismObject<ShadowType> 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();
Expand Down Expand Up @@ -334,8 +334,10 @@ private void traceObjectSynchronization(ObjectSynchronizationType obejctSynchron
}
}

private <F extends FocusType> boolean checkSynchronizationPolicy(SynchronizationContext<F> syncCtx, SynchronizationEventInformation eventInfo, Task task, OperationResult subResult) {
private <F extends FocusType> boolean checkSynchronizationPolicy(SynchronizationContext<F> 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()
Expand All @@ -349,7 +351,7 @@ private <F extends FocusType> 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);
Expand All @@ -364,13 +366,6 @@ private <F extends FocusType> 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
Expand All @@ -380,8 +375,10 @@ private boolean isSynchronizationEnabled(ObjectSynchronizationType synchronizati
* @return
* @throws SchemaException
*/
private <F extends FocusType> boolean checkTaskConstraints(SynchronizationContext<F> syncCtx, SynchronizationEventInformation eventInfo, Task task, OperationResult subResult) throws SchemaException {
if (!satisfyTaskConstraints(syncCtx)) {
private <F extends FocusType> boolean checkTaskConstraints(SynchronizationContext<F> 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<PropertyDelta<?>> modifications = createShadowIntentAndSynchronizationTimestampDelta(syncCtx,
Expand All @@ -397,34 +394,11 @@ private <F extends FocusType> boolean checkTaskConstraints(SynchronizationContex
return true;
}

private <F extends FocusType> boolean satisfyTaskConstraints(SynchronizationContext<F> 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> T getPropertyValue(Task task, QName propertyName) {
PrismProperty<T> prop = task.getExtensionProperty(propertyName);
if (prop == null || prop.isEmpty()) {
return null;
}

return prop.getRealValue();
}

private <F extends FocusType> boolean checkProtected(SynchronizationContext<F> syncCtx, SynchronizationEventInformation eventInfo, Task task, OperationResult subResult) {
if (isProtected(syncCtx.getApplicableShadow())) {
private <F extends FocusType> boolean checkProtected(SynchronizationContext<F> syncCtx, SynchronizationEventInformation eventInfo) {
if (syncCtx.isProtected()) {
OperationResult subResult = syncCtx.getResult();
Task task = syncCtx.getTask();
List<PropertyDelta<?>> modifications = createShadowIntentAndSynchronizationTimestampDelta(syncCtx, true);
executeShadowModifications(syncCtx.getApplicableShadow(), modifications, task, subResult);
subResult.recordSuccess();
Expand All @@ -436,21 +410,9 @@ private <F extends FocusType> boolean checkProtected(SynchronizationContext<F> s
return true;
}

private boolean isProtected(PrismObject<ShadowType> shadow) {
if (shadow == null) {
return false;
}

ShadowType currentShadowType = shadow.asObjectable();
if (currentShadowType.isProtectedObject() == null) {
return false;
}

return currentShadowType.isProtectedObject();
}

private <F extends FocusType> boolean checkDryRunAndUnrelatedChange(SynchronizationContext<F> syncCtx, SynchronizationEventInformation eventInfo, ResourceObjectShadowChangeDescription change, XMLGregorianCalendar now, Task task, OperationResult subResult) throws SchemaException {

private <F extends FocusType> boolean checkDryRunAndUnrelatedChange(SynchronizationContext<F> 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);
Expand Down Expand Up @@ -558,8 +520,10 @@ private void validate(ResourceObjectShadowChangeDescription change) {
* {@link SynchronizationSituationType#DISPUTED} situation
*/
private <F extends FocusType> void setupSituation(SynchronizationContext<F> 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.");

Expand Down Expand Up @@ -814,8 +778,7 @@ private ChangeType getModificationType(ResourceObjectShadowChangeDescription cha
}

private <F extends FocusType> SynchronizationSituationType reactToChange(SynchronizationContext<F> syncCtx,
ResourceObjectShadowChangeDescription change, boolean logDebug,
Task task, OperationResult parentResult)
ResourceObjectShadowChangeDescription change, boolean logDebug)
throws ConfigurationException, ObjectNotFoundException, SchemaException,
PolicyViolationException, ExpressionEvaluationException, ObjectAlreadyExistsException,
CommunicationException, SecurityViolationException {
Expand Down Expand Up @@ -855,6 +818,9 @@ private <F extends FocusType> SynchronizationSituationType reactToChange(Synchro

final boolean willSynchronize = isSynchronize(syncCtx.getReaction());
LensContext<F> lensContext = null;

OperationResult parentResult = syncCtx.getResult();
Task task = syncCtx.getTask();
if (willSynchronize) {
lensContext = createLensContext(syncCtx, change, syncCtx.getReaction(), options, parentResult);
}
Expand Down Expand Up @@ -1115,12 +1081,15 @@ private <F extends FocusType> void findReactionDefinition(SynchronizationContext
* Saves situation, timestamps, kind and intent (if needed)
*/
private <F extends FocusType> PrismObject<ShadowType> saveSyncMetadata(SynchronizationContext<F> syncCtx, ResourceObjectShadowChangeDescription change,
XMLGregorianCalendar now, Task task, OperationResult parentResult) {
XMLGregorianCalendar now) {
PrismObject<ShadowType> shadow = syncCtx.getCurrentShadow();
if (shadow == null) {
return null;
}

OperationResult parentResult = syncCtx.getResult();
Task task = syncCtx.getTask();

try {
ShadowType shadowType = shadow.asObjectable();
// new situation description
Expand Down

0 comments on commit 59956c9

Please sign in to comment.