Search in sources :

Example 1 with Change

use of com.evolveum.midpoint.provisioning.ucf.api.Change in project midpoint by Evolveum.

the class ShadowCache method synchronize.

///////////////////////////////////////////////////////////////////////////
// TODO: maybe split this to a separate class
///////////////////////////////////////////////////////////////////////////
public int synchronize(ResourceShadowDiscriminator shadowCoordinates, PrismProperty<?> lastToken, Task task, OperationResult parentResult) throws ObjectNotFoundException, CommunicationException, GenericFrameworkException, SchemaException, ConfigurationException, SecurityViolationException, ObjectAlreadyExistsException, ExpressionEvaluationException {
    InternalMonitor.recordShadowOtherOperation();
    final ProvisioningContext ctx = ctxFactory.create(shadowCoordinates, task, parentResult);
    List<Change> changes = null;
    try {
        changes = resouceObjectConverter.fetchChanges(ctx, lastToken, parentResult);
        LOGGER.trace("Found {} change(s). Start processing it (them).", changes.size());
        int processedChanges = 0;
        for (Change change : changes) {
            if (change.isTokenOnly()) {
                LOGGER.trace("Found token-only change: {}", change);
                task.setExtensionProperty(change.getToken());
                continue;
            }
            ObjectClassComplexTypeDefinition changeObjectClassDefinition = change.getObjectClassDefinition();
            ProvisioningContext shadowCtx;
            PrismObject<ShadowType> oldShadow = null;
            if (changeObjectClassDefinition == null) {
                if (change.getObjectDelta() != null && change.getObjectDelta().isDelete()) {
                    oldShadow = change.getOldShadow();
                    if (oldShadow == null) {
                        oldShadow = shadowManager.findOrAddShadowFromChangeGlobalContext(ctx, change, parentResult);
                    }
                    if (oldShadow == null) {
                        LOGGER.debug("No old shadow for delete synchronization event {}, we probably did not know about that object anyway, so well be ignoring this event", change);
                        continue;
                    }
                    shadowCtx = ctx.spawn(oldShadow);
                } else {
                    throw new SchemaException("No object class definition in change " + change);
                }
            } else {
                shadowCtx = ctx.spawn(changeObjectClassDefinition.getTypeName());
            }
            processChange(shadowCtx, change, oldShadow, parentResult);
            // such a change should be skipped to process consistent changes
            if (change.getOldShadow() == null) {
                PrismProperty<?> newToken = change.getToken();
                task.setExtensionProperty(newToken);
                processedChanges++;
                // because
                task.setProgress(task.getProgress() + 1);
                // processedChanges
                // are reflected
                // into task
                // only at task
                // run finish
                LOGGER.debug("Skipping processing change. Can't find appropriate shadow (e.g. the object was deleted on the resource meantime).");
                continue;
            }
            boolean isSuccess = processSynchronization(shadowCtx, change, parentResult);
            boolean retryUnhandledError = true;
            if (task.getExtension() != null) {
                PrismProperty tokenRetryUnhandledErrProperty = task.getExtensionProperty(SchemaConstants.SYNC_TOKEN_RETRY_UNHANDLED);
                if (tokenRetryUnhandledErrProperty != null) {
                    retryUnhandledError = (boolean) tokenRetryUnhandledErrProperty.getRealValue();
                }
            }
            if (!retryUnhandledError || isSuccess) {
                // // get updated token from change,
                // // create property modification from new token
                // // and replace old token with the new one
                PrismProperty<?> newToken = change.getToken();
                task.setExtensionProperty(newToken);
                processedChanges++;
                // because
                task.setProgress(task.getProgress() + 1);
            // processedChanges
            // are reflected
            // into task
            // only at task
            // run finish
            }
        }
        // also if no changes was detected, update token
        if (changes.isEmpty() && lastToken != null) {
            LOGGER.trace("No changes to synchronize on " + ctx.getResource());
            task.setExtensionProperty(lastToken);
        }
        task.savePendingModifications(parentResult);
        return processedChanges;
    } catch (SchemaException | CommunicationException | GenericFrameworkException | ConfigurationException | ObjectNotFoundException | ObjectAlreadyExistsException | ExpressionEvaluationException | RuntimeException | Error ex) {
        parentResult.recordFatalError(ex);
        throw ex;
    }
}
Also used : GenericFrameworkException(com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException) Change(com.evolveum.midpoint.provisioning.ucf.api.Change)

Example 2 with Change

use of com.evolveum.midpoint.provisioning.ucf.api.Change in project midpoint by Evolveum.

the class ResourceEventListenerImpl method notifyEvent.

@Override
public void notifyEvent(ResourceEventDescription eventDescription, Task task, OperationResult parentResult) throws SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, ObjectNotFoundException, GenericConnectorException, ObjectAlreadyExistsException, ExpressionEvaluationException {
    Validate.notNull(eventDescription, "Event description must not be null.");
    Validate.notNull(task, "Task must not be null.");
    Validate.notNull(parentResult, "Operation result must not be null");
    LOGGER.trace("Received event notification with the description: {}", eventDescription.debugDump());
    if (eventDescription.getCurrentShadow() == null && eventDescription.getDelta() == null) {
        throw new IllegalStateException("Neither current shadow, nor delta specified. It is required to have at least one of them specified.");
    }
    applyDefinitions(eventDescription, parentResult);
    PrismObject<ShadowType> shadow = null;
    shadow = eventDescription.getShadow();
    ShadowCache shadowCache = getShadowCache(Mode.STANDARD);
    ProvisioningContext ctx = provisioningContextFactory.create(shadow, task, parentResult);
    ctx.assertDefinition();
    Collection<ResourceAttribute<?>> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow);
    Change change = new Change(identifiers, eventDescription.getCurrentShadow(), eventDescription.getOldShadow(), eventDescription.getDelta());
    ObjectClassComplexTypeDefinition objectClassDefinition = ShadowUtil.getObjectClassDefinition(shadow);
    change.setObjectClassDefinition(objectClassDefinition);
    ShadowType shadowType = shadow.asObjectable();
    LOGGER.trace("Start to precess change: {}", change.toString());
    shadowCache.processChange(ctx, change, null, parentResult);
    LOGGER.trace("Change after processing {} . Start synchronizing.", change.toString());
    shadowCache.processSynchronization(ctx, change, parentResult);
}
Also used : ShadowType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType) ObjectClassComplexTypeDefinition(com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition) Change(com.evolveum.midpoint.provisioning.ucf.api.Change) ResourceAttribute(com.evolveum.midpoint.schema.processor.ResourceAttribute)

Example 3 with Change

use of com.evolveum.midpoint.provisioning.ucf.api.Change in project midpoint by Evolveum.

the class ConnectorInstanceConnIdImpl method fetchChanges.

@Override
public List<Change> fetchChanges(ObjectClassComplexTypeDefinition objectClass, PrismProperty<?> lastToken, AttributesToReturn attrsToReturn, StateReporter reporter, OperationResult parentResult) throws CommunicationException, GenericFrameworkException, SchemaException, ConfigurationException {
    OperationResult result = parentResult.createSubresult(ConnectorInstance.class.getName() + ".fetchChanges");
    result.addContext("objectClass", objectClass);
    result.addParam("lastToken", lastToken);
    // create sync token from the property last token
    SyncToken syncToken = null;
    try {
        syncToken = getSyncToken(lastToken);
        LOGGER.trace("Sync token created from the property last token: {}", syncToken == null ? null : syncToken.getValue());
    } catch (SchemaException ex) {
        result.recordFatalError(ex.getMessage(), ex);
        throw new SchemaException(ex.getMessage(), ex);
    }
    final List<SyncDelta> syncDeltas = new ArrayList<SyncDelta>();
    // get icf object class
    ObjectClass icfObjectClass;
    if (objectClass == null) {
        icfObjectClass = ObjectClass.ALL;
    } else {
        icfObjectClass = connIdNameMapper.objectClassToIcf(objectClass, getSchemaNamespace(), connectorType, legacySchema);
    }
    OperationOptionsBuilder optionsBuilder = new OperationOptionsBuilder();
    if (objectClass != null) {
        convertToIcfAttrsToGet(objectClass, attrsToReturn, optionsBuilder);
    }
    OperationOptions options = optionsBuilder.build();
    SyncResultsHandler syncHandler = new SyncResultsHandler() {

        @Override
        public boolean handle(SyncDelta delta) {
            LOGGER.trace("Detected sync delta: {}", delta);
            return syncDeltas.add(delta);
        }
    };
    OperationResult connIdResult = result.createSubresult(ConnectorFacade.class.getName() + ".sync");
    connIdResult.addContext("connector", connIdConnectorFacade.getClass());
    connIdResult.addArbitraryObjectAsParam("connIdObjectClass", icfObjectClass);
    connIdResult.addArbitraryObjectAsParam("syncToken", syncToken);
    connIdResult.addArbitraryObjectAsParam("syncHandler", syncHandler);
    SyncToken lastReceivedToken;
    try {
        InternalMonitor.recordConnectorOperation("sync");
        recordIcfOperationStart(reporter, ProvisioningOperation.ICF_SYNC, objectClass);
        lastReceivedToken = connIdConnectorFacade.sync(icfObjectClass, syncToken, syncHandler, options);
        recordIcfOperationEnd(reporter, ProvisioningOperation.ICF_SYNC, objectClass);
        connIdResult.recordSuccess();
        connIdResult.addReturn(OperationResult.RETURN_COUNT, syncDeltas.size());
    } catch (Throwable ex) {
        recordIcfOperationEnd(reporter, ProvisioningOperation.ICF_SYNC, objectClass, ex);
        Throwable midpointEx = processIcfException(ex, this, connIdResult);
        result.computeStatus();
        // exception
        if (midpointEx instanceof CommunicationException) {
            throw (CommunicationException) midpointEx;
        } else if (midpointEx instanceof GenericFrameworkException) {
            throw (GenericFrameworkException) midpointEx;
        } else if (midpointEx instanceof SchemaException) {
            throw (SchemaException) midpointEx;
        } else if (midpointEx instanceof RuntimeException) {
            throw (RuntimeException) midpointEx;
        } else if (midpointEx instanceof Error) {
            throw (Error) midpointEx;
        } else {
            throw new SystemException("Got unexpected exception: " + ex.getClass().getName() + ": " + ex.getMessage(), ex);
        }
    }
    // convert changes from icf to midpoint Change
    List<Change> changeList;
    try {
        changeList = getChangesFromSyncDeltas(icfObjectClass, syncDeltas, resourceSchema, result);
    } catch (SchemaException ex) {
        result.recordFatalError(ex.getMessage(), ex);
        throw new SchemaException(ex.getMessage(), ex);
    }
    if (lastReceivedToken != null) {
        Change lastChange = new Change((ObjectDelta) null, getToken(lastReceivedToken));
        LOGGER.trace("Adding last change: {}", lastChange);
        changeList.add(lastChange);
    }
    result.recordSuccess();
    result.addReturn(OperationResult.RETURN_COUNT, changeList == null ? 0 : changeList.size());
    return changeList;
}
Also used : OperationOptions(org.identityconnectors.framework.common.objects.OperationOptions) SchemaException(com.evolveum.midpoint.util.exception.SchemaException) ObjectClass(org.identityconnectors.framework.common.objects.ObjectClass) CommunicationException(com.evolveum.midpoint.util.exception.CommunicationException) GenericFrameworkException(com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException) OperationResult(com.evolveum.midpoint.schema.result.OperationResult) AsynchronousOperationResult(com.evolveum.midpoint.schema.result.AsynchronousOperationResult) Change(com.evolveum.midpoint.provisioning.ucf.api.Change) OperationOptionsBuilder(org.identityconnectors.framework.common.objects.OperationOptionsBuilder) SyncToken(org.identityconnectors.framework.common.objects.SyncToken) SyncDelta(org.identityconnectors.framework.common.objects.SyncDelta) SystemException(com.evolveum.midpoint.util.exception.SystemException) SyncResultsHandler(org.identityconnectors.framework.common.objects.SyncResultsHandler)

Example 4 with Change

use of com.evolveum.midpoint.provisioning.ucf.api.Change in project midpoint by Evolveum.

the class ConnectorInstanceConnIdImpl method getChangesFromSyncDeltas.

private List<Change> getChangesFromSyncDeltas(ObjectClass connIdObjClass, Collection<SyncDelta> connIdDeltas, PrismSchema schema, OperationResult parentResult) throws SchemaException, GenericFrameworkException {
    List<Change> changeList = new ArrayList<Change>();
    QName objectClass = connIdNameMapper.objectClassToQname(connIdObjClass, getSchemaNamespace(), legacySchema);
    ObjectClassComplexTypeDefinition objClassDefinition = null;
    if (objectClass != null) {
        objClassDefinition = (ObjectClassComplexTypeDefinition) schema.findComplexTypeDefinition(objectClass);
    }
    Validate.notNull(connIdDeltas, "Sync result must not be null.");
    for (SyncDelta icfDelta : connIdDeltas) {
        ObjectClass deltaIcfObjClass = connIdObjClass;
        QName deltaObjectClass = objectClass;
        ObjectClassComplexTypeDefinition deltaObjClassDefinition = objClassDefinition;
        if (objectClass == null) {
            deltaIcfObjClass = icfDelta.getObjectClass();
            deltaObjectClass = connIdNameMapper.objectClassToQname(deltaIcfObjClass, getSchemaNamespace(), legacySchema);
            if (deltaIcfObjClass != null) {
                deltaObjClassDefinition = (ObjectClassComplexTypeDefinition) schema.findComplexTypeDefinition(deltaObjectClass);
            }
        }
        if (deltaObjClassDefinition == null) {
            if (icfDelta.getDeltaType() == SyncDeltaType.DELETE) {
            // tolerate this. E.g. LDAP changelogs do not have objectclass in delete deltas.
            } else {
                throw new SchemaException("Got delta with object class " + deltaObjectClass + " (" + deltaIcfObjClass + ") that has no definition in resource schema");
            }
        }
        SyncDeltaType icfDeltaType = icfDelta.getDeltaType();
        if (SyncDeltaType.DELETE.equals(icfDeltaType)) {
            LOGGER.trace("START creating delta of type DELETE");
            ObjectDelta<ShadowType> objectDelta = new ObjectDelta<ShadowType>(ShadowType.class, ChangeType.DELETE, prismContext);
            Collection<ResourceAttribute<?>> identifiers = ConnIdUtil.convertToIdentifiers(icfDelta.getUid(), deltaObjClassDefinition, resourceSchema);
            Change change = new Change(identifiers, objectDelta, getToken(icfDelta.getToken()));
            change.setObjectClassDefinition(deltaObjClassDefinition);
            changeList.add(change);
            LOGGER.trace("END creating delta of type DELETE");
        } else if (SyncDeltaType.CREATE.equals(icfDeltaType)) {
            PrismObjectDefinition<ShadowType> objectDefinition = toShadowDefinition(deltaObjClassDefinition);
            LOGGER.trace("Object definition: {}", objectDefinition);
            LOGGER.trace("START creating delta of type CREATE");
            PrismObject<ShadowType> currentShadow = connIdConvertor.convertToResourceObject(icfDelta.getObject(), objectDefinition, false, caseIgnoreAttributeNames, legacySchema);
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Got current shadow: {}", currentShadow.debugDump());
            }
            Collection<ResourceAttribute<?>> identifiers = ShadowUtil.getAllIdentifiers(currentShadow);
            ObjectDelta<ShadowType> objectDelta = new ObjectDelta<ShadowType>(ShadowType.class, ChangeType.ADD, prismContext);
            objectDelta.setObjectToAdd(currentShadow);
            Change change = new Change(identifiers, objectDelta, getToken(icfDelta.getToken()));
            change.setObjectClassDefinition(deltaObjClassDefinition);
            changeList.add(change);
            LOGGER.trace("END creating delta of type CREATE");
        } else if (SyncDeltaType.CREATE_OR_UPDATE.equals(icfDeltaType) || SyncDeltaType.UPDATE.equals(icfDeltaType)) {
            PrismObjectDefinition<ShadowType> objectDefinition = toShadowDefinition(deltaObjClassDefinition);
            LOGGER.trace("Object definition: {}", objectDefinition);
            LOGGER.trace("START creating delta of type {}", icfDeltaType);
            PrismObject<ShadowType> currentShadow = connIdConvertor.convertToResourceObject(icfDelta.getObject(), objectDefinition, false, caseIgnoreAttributeNames, legacySchema);
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Got current shadow: {}", currentShadow.debugDump());
            }
            Collection<ResourceAttribute<?>> identifiers = ShadowUtil.getAllIdentifiers(currentShadow);
            Change change = new Change(identifiers, currentShadow, getToken(icfDelta.getToken()));
            change.setObjectClassDefinition(deltaObjClassDefinition);
            changeList.add(change);
            LOGGER.trace("END creating delta of type {}:\n{}", icfDeltaType, change.debugDump());
        } else {
            throw new GenericFrameworkException("Unexpected sync delta type " + icfDeltaType);
        }
    }
    return changeList;
}
Also used : SchemaException(com.evolveum.midpoint.util.exception.SchemaException) ObjectClass(org.identityconnectors.framework.common.objects.ObjectClass) SyncDeltaType(org.identityconnectors.framework.common.objects.SyncDeltaType) GenericFrameworkException(com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException) QName(javax.xml.namespace.QName) ShadowType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType) Change(com.evolveum.midpoint.provisioning.ucf.api.Change) SyncDelta(org.identityconnectors.framework.common.objects.SyncDelta) ObjectDelta(com.evolveum.midpoint.prism.delta.ObjectDelta)

Aggregations

Change (com.evolveum.midpoint.provisioning.ucf.api.Change)4 GenericFrameworkException (com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException)3 SchemaException (com.evolveum.midpoint.util.exception.SchemaException)2 ShadowType (com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType)2 ObjectClass (org.identityconnectors.framework.common.objects.ObjectClass)2 SyncDelta (org.identityconnectors.framework.common.objects.SyncDelta)2 ObjectDelta (com.evolveum.midpoint.prism.delta.ObjectDelta)1 ObjectClassComplexTypeDefinition (com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition)1 ResourceAttribute (com.evolveum.midpoint.schema.processor.ResourceAttribute)1 AsynchronousOperationResult (com.evolveum.midpoint.schema.result.AsynchronousOperationResult)1 OperationResult (com.evolveum.midpoint.schema.result.OperationResult)1 CommunicationException (com.evolveum.midpoint.util.exception.CommunicationException)1 SystemException (com.evolveum.midpoint.util.exception.SystemException)1 QName (javax.xml.namespace.QName)1 OperationOptions (org.identityconnectors.framework.common.objects.OperationOptions)1 OperationOptionsBuilder (org.identityconnectors.framework.common.objects.OperationOptionsBuilder)1 SyncDeltaType (org.identityconnectors.framework.common.objects.SyncDeltaType)1 SyncResultsHandler (org.identityconnectors.framework.common.objects.SyncResultsHandler)1 SyncToken (org.identityconnectors.framework.common.objects.SyncToken)1