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;
}
}
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);
}
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;
}
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;
}
Aggregations