use of com.evolveum.midpoint.util.exception.SchemaException in project midpoint by Evolveum.
the class ReconciliationProcessor method reconcileProjectionAttribute.
private <T> void reconcileProjectionAttribute(QName attrName, LensProjectionContext projCtx, Map<QName, DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<?>, PrismPropertyDefinition<?>>>> squeezedAttributes, RefinedObjectClassDefinition rOcDef, PrismObject<ShadowType> shadowNew, PrismContainer attributesContainer) throws SchemaException {
// LOGGER.trace("Attribute reconciliation processing attribute {}",attrName);
RefinedAttributeDefinition<T> attributeDefinition = projCtx.findAttributeDefinition(attrName);
if (attributeDefinition == null) {
String msg = "No definition for attribute " + attrName + " in " + projCtx.getResourceShadowDiscriminator();
throw new SchemaException(msg);
}
DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<T>, PrismPropertyDefinition<T>>> pvwoTriple = squeezedAttributes != null ? (DeltaSetTriple) squeezedAttributes.get(attrName) : null;
if (attributeDefinition.isIgnored(LayerType.MODEL)) {
LOGGER.trace("Skipping reconciliation of attribute {} because it is ignored", attrName);
return;
}
PropertyLimitations limitations = attributeDefinition.getLimitations(LayerType.MODEL);
if (limitations != null) {
PropertyAccessType access = limitations.getAccess();
if (access != null) {
if (projCtx.isAdd() && (access.isAdd() == null || !access.isAdd())) {
LOGGER.trace("Skipping reconciliation of attribute {} because it is non-createable", attrName);
return;
}
if (projCtx.isModify() && (access.isModify() == null || !access.isModify())) {
LOGGER.trace("Skipping reconciliation of attribute {} because it is non-updateable", attrName);
return;
}
}
}
Collection<ItemValueWithOrigin<PrismPropertyValue<T>, PrismPropertyDefinition<T>>> shouldBePValues;
if (pvwoTriple == null) {
shouldBePValues = new HashSet<>();
} else {
shouldBePValues = new HashSet<>(pvwoTriple.getNonNegativeValues());
}
// We consider values explicitly requested by user to be among "should be values".
addPropValuesFromDelta(shouldBePValues, projCtx.getPrimaryDelta(), attrName);
// But we DO NOT take values from sync delta (because they just reflect what's on the resource),
// nor from secondary delta (because these got there from mappings).
boolean hasStrongShouldBePValue = false;
for (ItemValueWithOrigin<? extends PrismPropertyValue<T>, PrismPropertyDefinition<T>> shouldBePValue : shouldBePValues) {
if (shouldBePValue.getMapping() != null && shouldBePValue.getMapping().getStrength() == MappingStrengthType.STRONG) {
hasStrongShouldBePValue = true;
break;
}
}
PrismProperty<T> attribute = attributesContainer.findProperty(attrName);
Collection<PrismPropertyValue<T>> arePValues;
if (attribute != null) {
arePValues = attribute.getValues();
} else {
arePValues = new HashSet<>();
}
// Too loud :-)
// if (LOGGER.isTraceEnabled()) {
// StringBuilder sb = new StringBuilder();
// sb.append("Reconciliation\nATTR: ").append(PrettyPrinter.prettyPrint(attrName));
// sb.append("\n Should be:");
// for (ItemValueWithOrigin<?,?> shouldBePValue : shouldBePValues) {
// sb.append("\n ");
// sb.append(shouldBePValue.getItemValue());
// PrismValueDeltaSetTripleProducer<?, ?> shouldBeMapping = shouldBePValue.getMapping();
// if (shouldBeMapping.getStrength() == MappingStrengthType.STRONG) {
// sb.append(" STRONG");
// }
// if (shouldBeMapping.getStrength() == MappingStrengthType.WEAK) {
// sb.append(" WEAK");
// }
// if (!shouldBePValue.isValid()) {
// sb.append(" INVALID");
// }
// }
// sb.append("\n Is:");
// for (PrismPropertyValue<Object> isPVal : arePValues) {
// sb.append("\n ");
// sb.append(isPVal);
// }
// LOGGER.trace("{}", sb.toString());
// }
ValueMatcher<T> valueMatcher = ValueMatcher.createMatcher(attributeDefinition, matchingRuleRegistry);
boolean hasValue = false;
for (ItemValueWithOrigin<? extends PrismPropertyValue<T>, PrismPropertyDefinition<T>> shouldBePvwo : shouldBePValues) {
PrismValueDeltaSetTripleProducer<?, ?> shouldBeMapping = shouldBePvwo.getMapping();
if (shouldBeMapping == null) {
continue;
}
T shouldBeRealValue = shouldBePvwo.getItemValue().getValue();
if (shouldBeMapping.getStrength() != MappingStrengthType.STRONG && (!arePValues.isEmpty() || hasStrongShouldBePValue)) {
// weak or normal value and the attribute already has a
// value. Skip it.
// we cannot override it as it might have been legally
// changed directly on the projection resource object
LOGGER.trace("Skipping reconciliation of value {} of the attribute {}: the mapping is not strong", shouldBeRealValue, attributeDefinition.getName().getLocalPart());
continue;
}
if (!isInValues(valueMatcher, shouldBeRealValue, arePValues)) {
if (attributeDefinition.isSingleValue()) {
if (hasValue) {
throw new SchemaException("Attempt to set more than one value for single-valued attribute " + attrName + " in " + projCtx.getResourceShadowDiscriminator());
}
recordDelta(valueMatcher, projCtx, SchemaConstants.PATH_ATTRIBUTES, attributeDefinition, ModificationType.REPLACE, shouldBeRealValue, shouldBePvwo.getSource(), "it is given by a mapping");
} else {
recordDelta(valueMatcher, projCtx, SchemaConstants.PATH_ATTRIBUTES, attributeDefinition, ModificationType.ADD, shouldBeRealValue, shouldBePvwo.getSource(), "it is given by a mapping");
}
hasValue = true;
}
}
decideIfTolerate(projCtx, attributeDefinition, arePValues, shouldBePValues, valueMatcher);
}
use of com.evolveum.midpoint.util.exception.SchemaException in project midpoint by Evolveum.
the class ReconciliationProcessor method processReconciliationFocus.
private <F extends ObjectType> void processReconciliationFocus(LensContext<F> context, LensProjectionContext projCtx, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
OperationResult subResult = result.createMinorSubresult(PROCESS_RECONCILIATION);
try {
// reconciliation is cheap if the shadow is already fetched therefore just do it
if (!projCtx.isDoReconciliation() && !projCtx.isFullShadow()) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Skipping reconciliation of {}: no doReconciliation and no full shadow", projCtx.getHumanReadableName());
}
return;
}
SynchronizationPolicyDecision policyDecision = projCtx.getSynchronizationPolicyDecision();
if (policyDecision != null && (policyDecision == SynchronizationPolicyDecision.DELETE || policyDecision == SynchronizationPolicyDecision.UNLINK)) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Skipping reconciliation of {}: decision={}", projCtx.getHumanReadableName(), policyDecision);
}
return;
}
if (projCtx.getObjectCurrent() == null) {
LOGGER.warn("Can't do reconciliation. Account context doesn't contain current version of account.");
return;
}
if (!projCtx.isFullShadow()) {
// We need to load the object
GetOperationOptions rootOps = GetOperationOptions.createDoNotDiscovery();
rootOps.setPointInTimeType(PointInTimeType.FUTURE);
PrismObject<ShadowType> objectOld = provisioningService.getObject(ShadowType.class, projCtx.getOid(), SelectorOptions.createCollection(rootOps), task, result);
ShadowType oldShadow = objectOld.asObjectable();
projCtx.determineFullShadowFlag(oldShadow.getFetchResult());
projCtx.setLoadedObject(objectOld);
projCtx.recompute();
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Starting reconciliation of {}", projCtx.getHumanReadableName());
}
reconcileAuxiliaryObjectClasses(projCtx);
RefinedObjectClassDefinition rOcDef = projCtx.getCompositeObjectClassDefinition();
Map<QName, DeltaSetTriple<ItemValueWithOrigin<PrismPropertyValue<?>, PrismPropertyDefinition<?>>>> squeezedAttributes = projCtx.getSqueezedAttributes();
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Attribute reconciliation processing {}", projCtx.getHumanReadableName());
}
reconcileProjectionAttributes(projCtx, squeezedAttributes, rOcDef);
Map<QName, DeltaSetTriple<ItemValueWithOrigin<PrismContainerValue<ShadowAssociationType>, PrismContainerDefinition<ShadowAssociationType>>>> squeezedAssociations = projCtx.getSqueezedAssociations();
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Association reconciliation processing {}", projCtx.getHumanReadableName());
}
reconcileProjectionAssociations(projCtx, squeezedAssociations, rOcDef, task, result);
reconcileMissingAuxiliaryObjectClassAttributes(projCtx);
} catch (RuntimeException | SchemaException e) {
subResult.recordFatalError(e);
throw e;
} finally {
subResult.computeStatus();
}
}
use of com.evolveum.midpoint.util.exception.SchemaException in project midpoint by Evolveum.
the class ContextLoader method createProjectionContext.
private <F extends FocusType> LensProjectionContext createProjectionContext(LensContext<F> context, PrismObject<ShadowType> account, Task task, OperationResult result) throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
ShadowType shadowType = account.asObjectable();
String resourceOid = ShadowUtil.getResourceOid(shadowType);
if (resourceOid == null) {
throw new SchemaException("The " + account + " has null resource reference OID");
}
String intent = ShadowUtil.getIntent(shadowType);
ShadowKindType kind = ShadowUtil.getKind(shadowType);
ResourceType resource = LensUtil.getResourceReadOnly(context, resourceOid, provisioningService, task, result);
String accountIntent = LensUtil.refineProjectionIntent(kind, intent, resource, prismContext);
ResourceShadowDiscriminator rsd = new ResourceShadowDiscriminator(resourceOid, kind, accountIntent);
LensProjectionContext accountSyncContext = context.findProjectionContext(rsd);
if (accountSyncContext != null) {
throw new SchemaException("Attempt to add " + account + " to a user that already contains account of type '" + accountIntent + "' on " + resource);
}
accountSyncContext = context.createProjectionContext(rsd);
accountSyncContext.setResource(resource);
accountSyncContext.setOid(account.getOid());
return accountSyncContext;
}
use of com.evolveum.midpoint.util.exception.SchemaException in project midpoint by Evolveum.
the class ContextLoader method getOrCreateAccountContext.
private <F extends FocusType> LensProjectionContext getOrCreateAccountContext(LensContext<F> context, PrismObject<ShadowType> projection, Task task, OperationResult result) throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, PolicyViolationException, ExpressionEvaluationException {
ShadowType accountType = projection.asObjectable();
String resourceOid = ShadowUtil.getResourceOid(accountType);
if (resourceOid == null) {
throw new SchemaException("The " + projection + " has null resource reference OID");
}
LensProjectionContext projectionContext = context.findProjectionContextByOid(accountType.getOid());
if (projectionContext == null) {
String intent = ShadowUtil.getIntent(accountType);
ShadowKindType kind = ShadowUtil.getKind(accountType);
ResourceType resource = LensUtil.getResourceReadOnly(context, resourceOid, provisioningService, task, result);
intent = LensUtil.refineProjectionIntent(kind, intent, resource, prismContext);
boolean thombstone = false;
if (ShadowUtil.isDead(accountType)) {
thombstone = true;
}
ResourceShadowDiscriminator rsd = new ResourceShadowDiscriminator(resourceOid, kind, intent, thombstone);
projectionContext = LensUtil.getOrCreateProjectionContext(context, rsd);
if (projectionContext.getOid() == null) {
projectionContext.setOid(projection.getOid());
} else if (projection.getOid() != null && !projectionContext.getOid().equals(projection.getOid())) {
// slightly inefficient here and check for existing shadow existence
try {
GetOperationOptions rootOpt = GetOperationOptions.createPointInTimeType(PointInTimeType.FUTURE);
rootOpt.setDoNotDiscovery(true);
Collection<SelectorOptions<GetOperationOptions>> opts = SelectorOptions.createCollection(rootOpt);
LOGGER.trace("Projection conflict detected, exsting: {}, new {}", projectionContext.getOid(), projection.getOid());
PrismObject<ShadowType> existingShadow = provisioningService.getObject(ShadowType.class, projectionContext.getOid(), opts, task, result);
// Maybe it is the other way around
try {
PrismObject<ShadowType> newShadow = provisioningService.getObject(ShadowType.class, projection.getOid(), opts, task, result);
// Obviously, two projections with the same discriminator exists
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Projection {} already exists in context\nExisting:\n{}\nNew:\n{}", new Object[] { rsd, existingShadow.debugDump(1), newShadow.debugDump(1) });
}
throw new PolicyViolationException("Projection " + rsd + " already exists in context (existing " + existingShadow + ", new " + projection);
} catch (ObjectNotFoundException e) {
// This is somehow expected, fix it and we can go on
result.muteLastSubresultError();
// We have to create new context in this case, but it has to have thumbstone set
rsd.setThombstone(true);
projectionContext = LensUtil.getOrCreateProjectionContext(context, rsd);
// We have to mark it as dead right now, otherwise the uniqueness check may fail
markShadowDead(projection.getOid(), result);
}
} catch (ObjectNotFoundException e) {
// This is somehow expected, fix it and we can go on
result.muteLastSubresultError();
String shadowOid = projectionContext.getOid();
projectionContext.getResourceShadowDiscriminator().setThombstone(true);
projectionContext = LensUtil.getOrCreateProjectionContext(context, rsd);
// We have to mark it as dead right now, otherwise the uniqueness check may fail
markShadowDead(shadowOid, result);
}
}
}
return projectionContext;
}
use of com.evolveum.midpoint.util.exception.SchemaException in project midpoint by Evolveum.
the class ContextLoader method finishLoadOfProjectionContext.
/**
* Check reconcile flag in account sync context and set accountOld
* variable if it's not set (from provisioning), load resource (if not set already), etc.
*/
private <F extends ObjectType> void finishLoadOfProjectionContext(LensContext<F> context, LensProjectionContext projContext, Task task, OperationResult result) throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
String projectionHumanReadableName = projContext.getHumanReadableName();
if (projContext.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.BROKEN) {
return;
}
// MID-2436 (volatile objects) - as a quick but effective hack, we set reconciliation:=TRUE for volatile accounts
ResourceObjectTypeDefinitionType objectDefinition = projContext.getResourceObjectTypeDefinitionType();
if (objectDefinition != null && objectDefinition.getVolatility() == ResourceObjectVolatilityType.UNPREDICTABLE && !projContext.isDoReconciliation()) {
LOGGER.trace("Resource object volatility is UNPREDICTABLE => setting doReconciliation to TRUE for {}", projContext.getResourceShadowDiscriminator());
projContext.setDoReconciliation(true);
}
// Remember OID before the object could be wiped
String projectionObjectOid = projContext.getOid();
if (projContext.isDoReconciliation() && !projContext.isFullShadow()) {
// The current object is useless here. So lets just wipe it so it will get loaded
projContext.setObjectCurrent(null);
}
// Load current object
boolean thombstone = false;
PrismObject<ShadowType> projectionObject = projContext.getObjectCurrent();
if (projContext.getObjectCurrent() == null || needToReload(context, projContext)) {
if (projContext.isAdd()) {
// No need to load old object, there is none
projContext.setExists(false);
projContext.recompute();
projectionObject = projContext.getObjectNew();
} else {
if (projectionObjectOid == null) {
projContext.setExists(false);
if (projContext.getResourceShadowDiscriminator() == null || projContext.getResourceShadowDiscriminator().getResourceOid() == null) {
throw new SystemException("Projection " + projectionHumanReadableName + " with null OID, no representation and no resource OID in account sync context " + projContext);
}
} else {
projContext.setExists(true);
GetOperationOptions rootOptions = GetOperationOptions.createPointInTimeType(PointInTimeType.FUTURE);
if (projContext.isDoReconciliation()) {
if (SchemaConstants.CHANGE_CHANNEL_DISCOVERY_URI.equals(context.getChannel())) {
// Avoid discovery loops
rootOptions.setDoNotDiscovery(true);
}
} else {
rootOptions.setNoFetch(true);
}
rootOptions.setAllowNotFound(true);
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(rootOptions);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Loading shadow {} for projection {}, options={}", projectionObjectOid, projectionHumanReadableName, options);
}
try {
PrismObject<ShadowType> objectOld = provisioningService.getObject(projContext.getObjectTypeClass(), projectionObjectOid, options, task, result);
if (LOGGER.isTraceEnabled()) {
if (!GetOperationOptions.isNoFetch(rootOptions) && !GetOperationOptions.isRaw(rootOptions)) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Full shadow loaded for {}:\n{}", projectionHumanReadableName, objectOld.debugDump(1));
}
}
}
Validate.notNull(objectOld.getOid());
if (InternalsConfig.consistencyChecks) {
String resourceOid = projContext.getResourceOid();
if (resourceOid != null && !resourceOid.equals(objectOld.asObjectable().getResourceRef().getOid())) {
throw new IllegalStateException("Loaded shadow with wrong resourceRef. Loading shadow " + projectionObjectOid + ", got " + objectOld.getOid() + ", expected resourceRef " + resourceOid + ", but was " + objectOld.asObjectable().getResourceRef().getOid() + " for context " + projectionHumanReadableName);
}
}
projContext.setLoadedObject(objectOld);
ShadowType oldShadow = objectOld.asObjectable();
if (projContext.isDoReconciliation()) {
projContext.determineFullShadowFlag(oldShadow.getFetchResult());
} else {
projContext.setFullShadow(false);
}
projectionObject = objectOld;
} catch (ObjectNotFoundException ex) {
// This does not mean BROKEN. The projection was there, but it gone now. What we really want here
// is a thombstone projection.
thombstone = true;
projContext.setFullShadow(false);
LOGGER.warn("Could not find object with oid {}. The projection context {} is marked as thombstone.", projectionObjectOid, projectionHumanReadableName);
} catch (CommunicationException | SchemaException | ConfigurationException | SecurityViolationException | RuntimeException | Error e) {
LOGGER.warn("Problem while getting object with oid {}. Projection context {} is marked as broken: {}: {}", projectionObjectOid, projectionHumanReadableName, e.getClass().getSimpleName(), e.getMessage());
projContext.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.BROKEN);
ResourceType resourceType = projContext.getResource();
if (resourceType == null) {
throw e;
} else {
ErrorSelectorType errorSelector = null;
if (resourceType.getConsistency() != null) {
errorSelector = resourceType.getConsistency().getConnectorErrorCriticality();
}
if (errorSelector == null) {
if (e instanceof SchemaException) {
// We cannot do any better.
return;
} else {
throw e;
}
} else {
if (ExceptionUtil.isSelected(errorSelector, e)) {
throw e;
} else {
return;
}
}
}
}
}
projContext.setFresh(true);
}
} else {
projectionObject = projContext.getObjectCurrent();
if (projectionObjectOid != null) {
projContext.setExists(true);
}
}
// Determine Resource
ResourceType resourceType = projContext.getResource();
String resourceOid = null;
if (resourceType == null) {
if (projectionObject != null) {
ShadowType shadowType = projectionObject.asObjectable();
resourceOid = ShadowUtil.getResourceOid(shadowType);
} else if (projContext.getResourceShadowDiscriminator() != null) {
resourceOid = projContext.getResourceShadowDiscriminator().getResourceOid();
} else if (!thombstone) {
throw new IllegalStateException("No shadow, no discriminator and not thombstone? That won't do. Projection " + projectionHumanReadableName);
}
} else {
resourceOid = resourceType.getOid();
}
// Determine discriminator
ResourceShadowDiscriminator discr = projContext.getResourceShadowDiscriminator();
if (discr == null) {
if (projectionObject != null) {
ShadowType accountShadowType = projectionObject.asObjectable();
String intent = ShadowUtil.getIntent(accountShadowType);
ShadowKindType kind = ShadowUtil.getKind(accountShadowType);
discr = new ResourceShadowDiscriminator(resourceOid, kind, intent, thombstone);
} else {
discr = new ResourceShadowDiscriminator(null, null, null, thombstone);
}
projContext.setResourceShadowDiscriminator(discr);
} else {
if (thombstone) {
// We do not want to reset thombstone flag if it was set before
discr.setThombstone(thombstone);
}
}
// Load resource
if (resourceType == null && resourceOid != null) {
resourceType = LensUtil.getResourceReadOnly(context, resourceOid, provisioningService, task, result);
projContext.setResource(resourceType);
}
//Determine refined schema and password policies for account type
RefinedObjectClassDefinition structuralObjectClassDef = projContext.getStructuralObjectClassDefinition();
if (structuralObjectClassDef != null) {
ObjectReferenceType passwordPolicyRef = structuralObjectClassDef.getPasswordPolicy();
if (passwordPolicyRef != null && passwordPolicyRef.getOid() != null) {
PrismObject<ValuePolicyType> passwordPolicy = cacheRepositoryService.getObject(ValuePolicyType.class, passwordPolicyRef.getOid(), null, result);
if (passwordPolicy != null) {
projContext.setAccountPasswordPolicy(passwordPolicy.asObjectable());
}
}
}
//set limitation, e.g. if this projection context should be recomputed and processed by projector
if (ModelExecuteOptions.isLimitPropagation(context.getOptions())) {
if (context.getTriggeredResourceOid() != null) {
if (!context.getTriggeredResourceOid().equals(resourceOid)) {
projContext.setCanProject(false);
}
}
}
setPrimaryDeltaOldValue(projContext);
}
Aggregations