use of com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions in project midpoint by Evolveum.
the class GetHelper method toProvisioningOperationOptions.
private ProvisioningOperationOptions toProvisioningOperationOptions(GetOperationOptions getOpts) {
if (getOpts == null) {
return null;
}
ProvisioningOperationOptions provisioningOpts = new ProvisioningOperationOptions();
// for now, we are interested in forceRetry option. In the future, there can be more.
provisioningOpts.setForceRetry(getOpts.getForceRetry());
return provisioningOpts;
}
use of com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions in project midpoint by Evolveum.
the class GetHelper method getShadow.
@NotNull
public PrismObject<ShadowType> getShadow(String oid, PrismObject<ShadowType> repoShadow, Collection<ResourceAttribute<?>> identifiersOverride, Collection<SelectorOptions<GetOperationOptions>> options, Task task, OperationResult parentResult) throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException, EncryptionException {
Validate.notNull(oid, "Object id must not be null.");
if (repoShadow == null) {
LOGGER.trace("Start getting object with oid {}; identifiers override = {}", oid, identifiersOverride);
} else {
LOGGER.trace("Start getting object '{}'; identifiers override = {}", repoShadow, identifiersOverride);
}
GetOperationOptions rootOptions = SelectorOptions.findRootOptions(options);
// have a fully cached object from the resource.
if (repoShadow == null) {
repoShadow = repositoryService.getObject(ShadowType.class, oid, null, parentResult);
LOGGER.trace("Got repository shadow object:\n{}", repoShadow.debugDumpLazily());
}
// Sanity check
if (!oid.equals(repoShadow.getOid())) {
parentResult.recordFatalError("Provided OID is not equal to OID of repository shadow");
throw new IllegalArgumentException("Provided OID is not equal to OID of repository shadow");
}
ProvisioningContext ctx;
try {
ctx = ctxFactory.createForShadow(repoShadow, task, parentResult);
ctx.setGetOperationOptions(options);
ctx.assertDefinition();
} catch (SchemaException | ConfigurationException | ObjectNotFoundException | CommunicationException | ExpressionEvaluationException e) {
if (isRaw(rootOptions)) {
// when using raw (repository option), return the repo shadow as it is. it's better than nothing and in this case we don't even need resource
// TODO maybe change assertDefinition to consider rawOption?
parentResult.computeStatusIfUnknown();
parentResult.muteError();
shadowCaretaker.updateShadowStateInEmergency(repoShadow);
return repoShadow;
}
throw e;
}
if (repoShadow.isImmutable()) {
repoShadow = shadowCaretaker.applyAttributesDefinitionToImmutable(ctx, repoShadow);
} else {
shadowCaretaker.applyAttributesDefinition(ctx, repoShadow);
}
ResourceType resource = ctx.getResource();
XMLGregorianCalendar now = clock.currentTimeXMLGregorianCalendar();
if (isNoFetch(rootOptions) || isRaw(rootOptions)) {
return processNoFetchGet(ctx, repoShadow, options, now, task, parentResult);
}
if (!ResourceTypeUtil.isReadCapabilityEnabled(resource)) {
UnsupportedOperationException e = new UnsupportedOperationException("Resource does not support 'read' operation");
parentResult.recordFatalError(e);
throw e;
}
if (ResourceTypeUtil.isInMaintenance(resource)) {
try {
MaintenanceException ex = new MaintenanceException("Resource " + resource + " is in the maintenance");
PrismObject<ShadowType> handledShadow = handleGetError(ctx, repoShadow, rootOptions, ex, task, parentResult);
validateShadow(handledShadow, true);
shadowCaretaker.applyAttributesDefinition(ctx, handledShadow);
shadowCaretaker.updateShadowState(ctx, handledShadow);
return handledShadow;
} catch (GenericFrameworkException | ObjectAlreadyExistsException | PolicyViolationException e) {
throw new SystemException(e.getMessage(), e);
}
}
if (shouldRefreshOnRead(resource, rootOptions)) {
LOGGER.trace("Refreshing {} before reading", repoShadow);
ProvisioningOperationOptions refreshOpts = toProvisioningOperationOptions(rootOptions);
RefreshShadowOperation refreshShadowOperation = refreshHelper.refreshShadow(repoShadow, refreshOpts, task, parentResult);
if (refreshShadowOperation != null) {
repoShadow = refreshShadowOperation.getRefreshedShadow();
}
LOGGER.trace("Refreshed repository shadow:\n{}", DebugUtil.debugDumpLazily(repoShadow, 1));
}
if (repoShadow == null) {
// Dead shadow was just removed
// TODO: is this OK? What about re-appeared objects
LOGGER.warn("DEAD shadow {} DEAD?", oid);
ObjectNotFoundException e = new ObjectNotFoundException("Resource object does not exist");
parentResult.recordFatalError(e);
throw e;
}
ShadowLifecycleStateType shadowState = shadowCaretaker.updateAndReturnShadowState(ctx, repoShadow, now);
LOGGER.trace("State of shadow {}: {}", repoShadow, shadowState);
if (canImmediatelyReturnCached(options, repoShadow, shadowState, resource)) {
LOGGER.trace("Returning cached (repository) version of shadow {}", repoShadow);
PrismObject<ShadowType> resultShadow = commonHelper.futurizeShadow(ctx, repoShadow, null, options, now);
shadowCaretaker.applyAttributesDefinition(ctx, resultShadow);
validateShadow(resultShadow, true);
return resultShadow;
}
PrismObject<ShadowType> resourceObject;
Collection<? extends ResourceAttribute<?>> identifiers;
if (identifiersOverride != null) {
identifiers = identifiersOverride;
} else {
Collection<? extends ResourceAttribute<?>> primaryIdentifiers = ShadowUtil.getPrimaryIdentifiers(repoShadow);
if (primaryIdentifiers == null || primaryIdentifiers.isEmpty()) {
if (ProvisioningUtil.hasPendingAddOperation(repoShadow) || ShadowUtil.isDead(repoShadow.asObjectable())) {
if (ProvisioningUtil.isFuturePointInTime(options)) {
// Get of uncreated or dead shadow, we want to see future state (how the shadow WILL look like).
// We cannot even try fetch operation here. We do not have the identifiers.
// But we have quite a good idea how the shadow is going to look like. Therefore we can return it.
PrismObject<ShadowType> resultShadow = commonHelper.futurizeShadow(ctx, repoShadow, null, options, now);
shadowCaretaker.applyAttributesDefinition(ctx, resultShadow);
validateShadow(resultShadow, true);
// re-trying the operation here would not provide big benefits and it will complicate the code.
return resultShadow;
} else {
// The object might have been created in the meantime.
throw new GenericConnectorException("Unable to get object from the resource. Probably it has not been created yet because " + "of previous unavailability of the resource.");
}
}
// No identifiers found
SchemaException ex = new SchemaException("No primary identifiers found in the repository shadow " + repoShadow + " with respect to " + resource);
parentResult.recordFatalError("No primary identifiers found in the repository shadow " + repoShadow, ex);
throw ex;
}
identifiers = ShadowUtil.getAllIdentifiers(repoShadow);
}
try {
try {
resourceObject = resourceObjectConverter.getResourceObject(ctx, identifiers, repoShadow, true, parentResult);
} catch (ObjectNotFoundException e) {
// This may be OK, e.g. for connectors that have running async add operation.
if (shadowState == ShadowLifecycleStateType.CONCEIVED || shadowState == ShadowLifecycleStateType.GESTATING) {
LOGGER.trace("{} was not found, but we can return cached shadow because it is in {} state", repoShadow, shadowState);
// we don't want to see 'warning-like' orange boxes in GUI (TODO reconsider this)
parentResult.deleteLastSubresultIfError();
parentResult.recordSuccess();
PrismObject<ShadowType> resultShadow = commonHelper.futurizeShadow(ctx, repoShadow, null, options, now);
shadowCaretaker.applyAttributesDefinition(ctx, resultShadow);
LOGGER.trace("Returning futurized shadow:\n{}", DebugUtil.debugDumpLazily(resultShadow));
validateShadow(resultShadow, true);
return resultShadow;
} else {
LOGGER.trace("{} was not found, following normal error processing because shadow is in {} state", repoShadow, shadowState);
// be caught later and the usual error handlers will bury the shadow.
throw e;
}
}
LOGGER.trace("Shadow returned by ResourceObjectConverter:\n{}", resourceObject.debugDumpLazily(1));
// TODO this looks like a hack. We should not set kind/intent to the resource object...
// Resource shadow may have different auxiliary object classes than
// the original repo shadow. Make sure we have the definition that
// applies to resource shadow. We will fix repo shadow later.
// BUT we need also information about kind/intent and these information is only
// in repo shadow, therefore the following 2 lines..
resourceObject.asObjectable().setKind(repoShadow.asObjectable().getKind());
resourceObject.asObjectable().setIntent(repoShadow.asObjectable().getIntent());
ProvisioningContext shadowCtx = ctx.spawnForShadow(resourceObject);
String operationCtx = "getting " + repoShadow + " was successful.";
resourceManager.modifyResourceAvailabilityStatus(resource.getOid(), AvailabilityStatusType.UP, operationCtx, task, parentResult, false);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Shadow from repository:\n{}", repoShadow.debugDump(1));
LOGGER.trace("Resource object fetched from resource:\n{}", resourceObject.debugDump(1));
}
repoShadow = shadowManager.updateShadow(shadowCtx, resourceObject, null, repoShadow, shadowState, parentResult);
LOGGER.trace("Repository shadow after update:\n{}", repoShadow.debugDumpLazily(1));
// Complete the shadow by adding attributes from the resource object
// This also completes the associations by adding shadowRefs
PrismObject<ShadowType> shadowedObject = shadowedObjectConstructionHelper.constructShadowedObject(shadowCtx, repoShadow, resourceObject, parentResult);
LOGGER.trace("Shadowed resource object:\n{}", shadowedObject.debugDumpLazily(1));
PrismObject<ShadowType> resultShadow = commonHelper.futurizeShadow(ctx, repoShadow, shadowedObject, options, now);
LOGGER.trace("Futurized shadowed resource:\n{}", resultShadow.debugDumpLazily(1));
parentResult.recordSuccess();
validateShadow(resultShadow, true);
return resultShadow;
} catch (Exception ex) {
try {
PrismObject<ShadowType> handledShadow = handleGetError(ctx, repoShadow, rootOptions, ex, task, parentResult);
if (handledShadow == null) {
throw ex;
}
if (parentResult.getStatus() == OperationResultStatus.FATAL_ERROR) {
// We are going to return an object. Therefore this cannot
// be fatal error, as at least some information
// is returned
parentResult.setStatus(OperationResultStatus.PARTIAL_ERROR);
}
// We update the shadow lifecycle state because we are not sure if the handledShadow is the same
// as repoShadow (that has its state set).
// must be called before futurizeShadow
shadowCaretaker.updateShadowState(ctx, handledShadow);
PrismObject<ShadowType> futurizedShadow = commonHelper.futurizeShadow(ctx, handledShadow, null, options, now);
validateShadow(futurizedShadow, true);
return futurizedShadow;
} catch (GenericFrameworkException | ObjectAlreadyExistsException | PolicyViolationException e) {
throw new SystemException(e.getMessage(), e);
}
} finally {
// We need to record the fetch down here. Now it is certain that we
// are going to fetch from resource (we do not have raw/noFetch option)
InternalMonitor.recordCount(InternalCounters.SHADOW_FETCH_OPERATION_COUNT);
}
}
use of com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions in project midpoint by Evolveum.
the class ChangeExecutor method executeModification.
private <T extends ObjectType, F extends ObjectType> void executeModification(ObjectDelta<T> change, LensContext<F> context, LensElementContext<T> objectContext, ModelExecuteOptions options, ResourceType resource, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
Class<T> objectTypeClass = change.getObjectTypeClass();
PrismObject<T> objectNew = objectContext.getObjectNew();
OwnerResolver ownerResolver = createOwnerResolver(context, task, result);
try {
securityEnforcer.authorize(ModelAuthorizationAction.MODIFY.getUrl(), AuthorizationPhaseType.EXECUTION, objectNew, change, null, ownerResolver, result);
metadataManager.applyMetadataModify(change, objectContext, objectTypeClass, clock.currentTimeXMLGregorianCalendar(), task, context, result);
if (change.isEmpty()) {
// Nothing to do
return;
}
if (TaskType.class.isAssignableFrom(objectTypeClass)) {
taskManager.modifyTask(change.getOid(), change.getModifications(), result);
} else if (NodeType.class.isAssignableFrom(objectTypeClass)) {
throw new UnsupportedOperationException("NodeType is not modifiable using model interface");
} else if (ObjectTypes.isClassManagedByProvisioning(objectTypeClass)) {
ProvisioningOperationOptions provisioningOptions = getProvisioningOptions(context, options);
String oid = modifyProvisioningObject(objectTypeClass, change.getOid(), change.getModifications(), context, objectContext, provisioningOptions, resource, task, result);
if (!oid.equals(change.getOid())) {
change.setOid(oid);
}
} else {
FocusConstraintsChecker.clearCacheForDelta(change.getModifications());
cacheRepositoryService.modifyObject(objectTypeClass, change.getOid(), change.getModifications(), result);
}
task.recordObjectActionExecuted(objectNew, objectTypeClass, change.getOid(), ChangeType.MODIFY, context.getChannel(), null);
} catch (Throwable t) {
task.recordObjectActionExecuted(objectNew, objectTypeClass, change.getOid(), ChangeType.MODIFY, context.getChannel(), t);
throw t;
}
}
use of com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions in project midpoint by Evolveum.
the class ChangeExecutor method updateSituationInShadow.
private <F extends ObjectType> void updateSituationInShadow(Task task, SynchronizationSituationType situation, LensFocusContext<F> focusContext, LensProjectionContext projectionCtx, OperationResult parentResult) throws ObjectNotFoundException, SchemaException {
String projectionOid = projectionCtx.getOid();
OperationResult result = new OperationResult(OPERATION_UPDATE_SITUATION_ACCOUNT);
result.addParam("situation", situation);
result.addParam("accountRef", projectionOid);
PrismObject<ShadowType> account = null;
GetOperationOptions getOptions = GetOperationOptions.createNoFetch();
getOptions.setAllowNotFound(true);
try {
account = provisioning.getObject(ShadowType.class, projectionOid, SelectorOptions.createCollection(getOptions), task, result);
} catch (Exception ex) {
LOGGER.trace("Problem with getting account, skipping modifying situation in account.");
return;
}
List<PropertyDelta<?>> syncSituationDeltas = SynchronizationUtils.createSynchronizationSituationAndDescriptionDelta(account, situation, task.getChannel(), projectionCtx.hasFullShadow());
try {
Utils.setRequestee(task, focusContext);
ProvisioningOperationOptions options = ProvisioningOperationOptions.createCompletePostponed(false);
options.setDoNotDiscovery(true);
String changedOid = provisioning.modifyObject(ShadowType.class, projectionOid, syncSituationDeltas, null, options, task, result);
// modifyProvisioningObject(AccountShadowType.class, accountRef,
// syncSituationDeltas,
// ProvisioningOperationOptions.createCompletePostponed(false),
// task, result);
projectionCtx.setSynchronizationSituationResolved(situation);
LOGGER.trace("Situation in projection {} was updated to {}.", projectionCtx, situation);
} catch (ObjectNotFoundException ex) {
// if the object not found exception is thrown, it's ok..probably
// the account was deleted by previous execution of changes..just
// log in the trace the message for the user..
LOGGER.trace("Situation in account could not be updated. Account not found on the resource. Skipping modifying situation in account");
return;
} catch (Exception ex) {
throw new SystemException(ex.getMessage(), ex);
} finally {
Utils.clearRequestee(task);
}
// if everything is OK, add result of the situation modification to the
// parent result
result.recordSuccess();
parentResult.addSubresult(result);
}
use of com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions in project midpoint by Evolveum.
the class OperationCompletionActivityRun method processItem.
@Override
public boolean processItem(@NotNull ShadowType object, @NotNull ItemProcessingRequest<ShadowType> request, RunningTask workerTask, OperationResult result) throws CommonException {
RepositoryCache.enterLocalCaches(getModelBeans().cacheConfigurationManager);
try {
ProvisioningOperationOptions options = ProvisioningOperationOptions.createForceRetry(Boolean.TRUE);
ModelImplUtils.clearRequestee(workerTask);
getModelBeans().provisioningService.refreshShadow(object.asPrismObject(), options, workerTask, result);
return true;
} finally {
RepositoryCache.exitLocalCaches();
}
}
Aggregations