use of com.evolveum.midpoint.xml.ns._public.common.common_3.PartialProcessingTypeType.SKIP in project midpoint by Evolveum.
the class ProjectionCredentialsProcessor method processProjectionPasswordMapping.
private <F extends FocusType> void processProjectionPasswordMapping(LensContext<F> context, final LensProjectionContext projCtx, final ValuePolicyType passwordPolicy, XMLGregorianCalendar now, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException {
LensFocusContext<F> focusContext = context.getFocusContext();
PrismObject<F> userNew = focusContext.getObjectNew();
if (userNew == null) {
// This must be a user delete or something similar. No point in proceeding
LOGGER.trace("userNew is null, skipping credentials processing");
return;
}
PrismObjectDefinition<ShadowType> accountDefinition = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(ShadowType.class);
PrismPropertyDefinition<ProtectedStringType> projPasswordPropertyDefinition = accountDefinition.findPropertyDefinition(SchemaConstants.PATH_PASSWORD_VALUE);
ResourceShadowDiscriminator rsd = projCtx.getResourceShadowDiscriminator();
RefinedObjectClassDefinition refinedProjDef = projCtx.getStructuralObjectClassDefinition();
if (refinedProjDef == null) {
LOGGER.trace("No RefinedObjectClassDefinition, therefore also no password outbound definition, skipping credentials processing for projection {}", rsd);
return;
}
List<MappingType> outboundMappingTypes = refinedProjDef.getPasswordOutbound();
if (outboundMappingTypes == null || outboundMappingTypes.isEmpty()) {
LOGGER.trace("No outbound password mapping for {}, skipping credentials processing", rsd);
return;
}
// HACK
if (!projCtx.isDoReconciliation() && !projCtx.isAdd() && !isActivated(outboundMappingTypes, focusContext.getDelta())) {
LOGGER.trace("Outbound password mappings not activated for type {}, skipping credentials processing", rsd);
return;
}
final ObjectDelta<ShadowType> projDelta = projCtx.getDelta();
final PropertyDelta<ProtectedStringType> projPasswordDelta;
if (projDelta != null && projDelta.getChangeType() == MODIFY) {
projPasswordDelta = projDelta.findPropertyDelta(SchemaConstants.PATH_PASSWORD_VALUE);
} else {
projPasswordDelta = null;
}
checkExistingDeltaSanity(projCtx, projPasswordDelta);
boolean evaluateWeak = getEvaluateWeak(projCtx);
final ItemDeltaItem<PrismPropertyValue<PasswordType>, PrismPropertyDefinition<ProtectedStringType>> userPasswordIdi = focusContext.getObjectDeltaObject().findIdi(SchemaConstants.PATH_PASSWORD_VALUE);
StringPolicyResolver stringPolicyResolver = new StringPolicyResolver() {
@Override
public void setOutputPath(ItemPath outputPath) {
}
@Override
public void setOutputDefinition(ItemDefinition outputDefinition) {
}
@Override
public StringPolicyType resolve() {
if (passwordPolicy == null) {
return null;
}
return passwordPolicy.getStringPolicy();
}
};
MappingInitializer<PrismPropertyValue<ProtectedStringType>, PrismPropertyDefinition<ProtectedStringType>> initializer = (builder) -> {
builder.defaultTargetDefinition(projPasswordPropertyDefinition);
builder.defaultSource(new Source<>(userPasswordIdi, ExpressionConstants.VAR_INPUT));
builder.stringPolicyResolver(stringPolicyResolver);
return builder;
};
MappingOutputProcessor<PrismPropertyValue<ProtectedStringType>> processor = (mappingOutputPath, outputStruct) -> {
PrismValueDeltaSetTriple<PrismPropertyValue<ProtectedStringType>> outputTriple = outputStruct.getOutputTriple();
if (outputTriple == null) {
LOGGER.trace("Credentials 'password' expression resulted in null output triple, skipping credentials processing for {}", rsd);
return false;
}
boolean projectionIsNew = projDelta != null && (projDelta.getChangeType() == ChangeType.ADD || projCtx.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.ADD);
Collection<PrismPropertyValue<ProtectedStringType>> newValues = outputTriple.getPlusSet();
if (projectionIsNew) {
newValues = outputTriple.getNonNegativeValues();
} else {
newValues = outputTriple.getPlusSet();
}
if (!canGetCleartext(newValues)) {
ObjectDelta<ShadowType> projectionPrimaryDelta = projCtx.getPrimaryDelta();
if (projectionPrimaryDelta != null) {
PropertyDelta<ProtectedStringType> passwordPrimaryDelta = projectionPrimaryDelta.findPropertyDelta(SchemaConstants.PATH_PASSWORD_VALUE);
if (passwordPrimaryDelta != null) {
// We have only hashed value coming from the mapping. There are not very useful
// for provisioning. But we have primary projection delta - and that is very likely
// to be better.
// Skip all password mappings in this case. Primary delta trumps everything.
// No weak, normal or even strong mapping can change that.
// We need to disregard even strong mapping in this case. If we would heed the strong
// mapping then account initialization won't be possible.
LOGGER.trace("We have primary password delta in projection, skipping credentials processing");
return false;
}
}
}
return true;
};
mappingEvaluator.evaluateOutboundMapping(context, projCtx, outboundMappingTypes, SchemaConstants.PATH_PASSWORD_VALUE, SchemaConstants.PATH_PASSWORD_VALUE, initializer, processor, now, true, evaluateWeak, "password mapping", task, result);
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.PartialProcessingTypeType.SKIP in project midpoint by Evolveum.
the class OutboundProcessor method evaluateMapping.
private <F extends FocusType, V extends PrismValue, D extends ItemDefinition> Mapping<V, D> evaluateMapping(final Mapping.Builder<V, D> mappingBuilder, QName mappingQName, D targetDefinition, ObjectDeltaObject<F> focusOdo, ObjectDeltaObject<ShadowType> projectionOdo, String operation, RefinedObjectClassDefinition rOcDef, RefinedObjectClassDefinition assocTargetObjectClassDefinition, LensContext<F> context, LensProjectionContext projCtx, final Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException {
if (!mappingBuilder.isApplicableToChannel(context.getChannel())) {
LOGGER.trace("Skipping outbound mapping for {} because the channel does not match", mappingQName);
return null;
}
// TODO: check access
// This is just supposed to be an optimization. The consolidation should deal with the weak mapping
// even if it is there. But in that case we do not need to evaluate it at all.
// Edit 2017-02-16 pmed: It's not quite true. If the attribute is non-tolerant, it will get removed if we would
// skip evaluation of this mapping. So we really need to do this.
// if (mappingBuilder.getStrength() == MappingStrengthType.WEAK && projCtx.hasValueForAttribute(mappingQName)) {
// LOGGER.trace("Skipping outbound mapping for {} because it is weak", mappingQName);
// return null;
// }
mappingBuilder.setDefaultTargetDefinition(targetDefinition);
mappingBuilder.setSourceContext(focusOdo);
mappingBuilder.setMappingQName(mappingQName);
mappingBuilder.addVariableDefinition(ExpressionConstants.VAR_USER, focusOdo);
mappingBuilder.addVariableDefinition(ExpressionConstants.VAR_FOCUS, focusOdo);
mappingBuilder.addVariableDefinition(ExpressionConstants.VAR_ACCOUNT, projectionOdo);
mappingBuilder.addVariableDefinition(ExpressionConstants.VAR_SHADOW, projectionOdo);
mappingBuilder.addVariableDefinition(ExpressionConstants.VAR_PROJECTION, projectionOdo);
mappingBuilder.addVariableDefinition(ExpressionConstants.VAR_CONFIGURATION, context.getSystemConfiguration());
mappingBuilder.addVariableDefinition(ExpressionConstants.VAR_ITERATION, LensUtil.getIterationVariableValue(projCtx));
mappingBuilder.addVariableDefinition(ExpressionConstants.VAR_ITERATION_TOKEN, LensUtil.getIterationTokenVariableValue(projCtx));
mappingBuilder.addVariableDefinition(ExpressionConstants.VAR_RESOURCE, projCtx.getResource());
mappingBuilder.addVariableDefinition(ExpressionConstants.VAR_OPERATION, operation);
if (assocTargetObjectClassDefinition != null) {
mappingBuilder.addVariableDefinition(ExpressionConstants.VAR_ASSOCIATION_TARGET_OBJECT_CLASS_DEFINITION, assocTargetObjectClassDefinition);
}
mappingBuilder.setRootNode(focusOdo);
mappingBuilder.setOriginType(OriginType.OUTBOUND);
mappingBuilder.setRefinedObjectClassDefinition(rOcDef);
StringPolicyResolver stringPolicyResolver = new StringPolicyResolver() {
private ItemPath outputPath;
private ItemDefinition outputDefinition;
@Override
public void setOutputPath(ItemPath outputPath) {
this.outputPath = outputPath;
}
@Override
public void setOutputDefinition(ItemDefinition outputDefinition) {
this.outputDefinition = outputDefinition;
}
@Override
public StringPolicyType resolve() {
if (mappingBuilder.getMappingType().getExpression() != null) {
List<JAXBElement<?>> evaluators = mappingBuilder.getMappingType().getExpression().getExpressionEvaluator();
for (JAXBElement jaxbEvaluator : evaluators) {
Object object = jaxbEvaluator.getValue();
if (object instanceof GenerateExpressionEvaluatorType && ((GenerateExpressionEvaluatorType) object).getValuePolicyRef() != null) {
ObjectReferenceType ref = ((GenerateExpressionEvaluatorType) object).getValuePolicyRef();
try {
ValuePolicyType valuePolicyType = mappingBuilder.getObjectResolver().resolve(ref, ValuePolicyType.class, null, "resolving value policy for generate attribute " + outputDefinition.getName() + "value", task, new OperationResult("Resolving value policy"));
if (valuePolicyType != null) {
return valuePolicyType.getStringPolicy();
}
} catch (CommonException ex) {
throw new SystemException(ex.getMessage(), ex);
}
}
}
}
return null;
}
};
mappingBuilder.setStringPolicyResolver(stringPolicyResolver);
// (e.g. in old values in ADD situations and new values in DELETE situations).
if (focusOdo.getOldObject() == null) {
mappingBuilder.setConditionMaskOld(false);
}
if (focusOdo.getNewObject() == null) {
mappingBuilder.setConditionMaskNew(false);
}
Mapping<V, D> mapping = mappingBuilder.build();
mappingEvaluator.evaluateMapping(mapping, context, projCtx, task, result);
return mapping;
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.PartialProcessingTypeType.SKIP in project midpoint by Evolveum.
the class ProjectionValuesProcessor method processProjections.
private <F extends FocusType> void processProjections(LensContext<F> context, LensProjectionContext projContext, String activityDescription, Task task, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException, PolicyViolationException {
checkSchemaAndPolicies(context, projContext, activityDescription, result);
SynchronizationPolicyDecision policyDecision = projContext.getSynchronizationPolicyDecision();
if (policyDecision != null && policyDecision == SynchronizationPolicyDecision.UNLINK) {
// we cannot skip deleted accounts here as the delete delta will be skipped as well
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Skipping processing of value for {} because the decision is {}", projContext.getHumanReadableName(), policyDecision);
}
return;
}
if (consistencyChecks)
context.checkConsistence();
if (!projContext.hasFullShadow() && hasIterationExpression(projContext)) {
contextLoader.loadFullShadow(context, projContext, "iteration expression", task, result);
if (projContext.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.BROKEN) {
return;
}
}
int maxIterations = determineMaxIterations(projContext);
int iteration = 0;
String iterationToken = null;
boolean wasResetIterationCounter = false;
PrismObject<ShadowType> shadowCurrent = projContext.getObjectCurrent();
if (shadowCurrent != null) {
Integer shadowIteration = shadowCurrent.asObjectable().getIteration();
if (shadowIteration != null) {
iteration = shadowIteration;
}
iterationToken = shadowCurrent.asObjectable().getIterationToken();
}
boolean skipUniquenessCheck = false;
while (true) {
projContext.setIteration(iteration);
if (iterationToken == null) {
iterationToken = formatIterationToken(context, projContext, iteration, task, result);
}
projContext.setIterationToken(iterationToken);
String conflictMessage;
// These are normally null. But there may be leftover from the previous iteration.
// While that should not affect the algorithm (it should overwrite it) it may confuse
// people during debugging and unecessarily clutter the debug output.
projContext.setOutboundConstruction(null);
projContext.setSqueezedAttributes(null);
projContext.setSqueezedAssociations(null);
LOGGER.trace("Projection values iteration {}, token '{}' for {}", iteration, iterationToken, projContext.getHumanReadableName());
if (!evaluateIterationCondition(context, projContext, iteration, iterationToken, true, task, result)) {
conflictMessage = "pre-iteration condition was false";
LOGGER.debug("Skipping iteration {}, token '{}' for {} because the pre-iteration condition was false", iteration, iterationToken, projContext.getHumanReadableName());
} else {
if (consistencyChecks)
context.checkConsistence();
// Re-evaluates the values in the account constructions (including roles)
assignmentProcessor.processAssignmentsAccountValues(projContext, result);
context.recompute();
if (consistencyChecks)
context.checkConsistence();
// LensUtil.traceContext(LOGGER, activityDescription, "values (assignment account values)", false, context, true);
// Evaluates the values in outbound mappings
outboundProcessor.processOutbound(context, projContext, task, result);
context.recompute();
if (consistencyChecks)
context.checkConsistence();
// LensUtil.traceContext(LOGGER, activityDescription, "values (outbound)", false, context, true);
// Merges the values together, processing exclusions and strong/weak mappings are needed
consolidationProcessor.consolidateValues(context, projContext, task, result);
if (consistencyChecks)
context.checkConsistence();
context.recompute();
if (consistencyChecks)
context.checkConsistence();
// Aux object classes may have changed during consolidation. Make sure we have up-to-date definitions.
context.refreshAuxiliaryObjectClassDefinitions();
// but I don't see any easier way to do it now.
if (iteration != 0 && !wasResetIterationCounter && willResetIterationCounter(projContext)) {
wasResetIterationCounter = true;
iteration = 0;
iterationToken = null;
cleanupContext(projContext);
LOGGER.trace("Resetting iteration counter and token because we have rename");
if (consistencyChecks)
context.checkConsistence();
continue;
}
if (policyDecision != null && policyDecision == SynchronizationPolicyDecision.DELETE) {
// No need to play the iterative game if the account is deleted
break;
}
// Check constraints
boolean conflict = true;
ShadowConstraintsChecker<F> checker = new ShadowConstraintsChecker<F>(projContext);
if (skipUniquenessCheck) {
skipUniquenessCheck = false;
conflict = false;
} else {
checker.setPrismContext(prismContext);
checker.setContext(context);
checker.setProvisioningService(provisioningService);
checker.check(task, result);
if (checker.isSatisfiesConstraints()) {
LOGGER.trace("Current shadow satisfies uniqueness constraints. Iteration {}, token '{}'", iteration, iterationToken);
conflict = false;
} else {
LOGGER.trace("Current shadow does not satisfy constraints. Conflicting shadow exists. Needed to found out what's wrong.");
if (checker.getConflictingShadow() != null) {
PrismObject<ShadowType> fullConflictingShadow = null;
try {
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(GetOperationOptions.createPointInTimeType(PointInTimeType.FUTURE));
fullConflictingShadow = provisioningService.getObject(ShadowType.class, checker.getConflictingShadow().getOid(), options, task, result);
} catch (ObjectNotFoundException ex) {
//if object not found exception occurred, its ok..the account was deleted by the discovery, so there esits no more conflicting shadow
LOGGER.trace("Conflicting shadow was deleted by discovery. It does not exist anymore. Continue with adding current shadow.");
conflict = false;
}
result.computeStatus();
// the situation which happend
if (result.isError()) {
result.muteError();
}
if (conflict) {
PrismObject<F> focus = repositoryService.searchShadowOwner(checker.getConflictingShadow().getOid(), SelectorOptions.createCollection(GetOperationOptions.createAllowNotFound()), result);
//the owner of the shadow exist and it is a current user..so the shadow was successfully created, linked etc..no other recompute is needed..
if (focus != null && focus.getOid().equals(context.getFocusContext().getOid())) {
LOGGER.trace("Conflicting projection already linked to the current focus, no recompute needed, continue processing with conflicting projection.");
// accountContext.setSecondaryDelta(null);
cleanupContext(projContext);
projContext.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.KEEP);
projContext.setObjectOld(fullConflictingShadow.clone());
projContext.setObjectCurrent(fullConflictingShadow);
projContext.setFullShadow(true);
ObjectDelta<ShadowType> secondaryDelta = projContext.getSecondaryDelta();
if (secondaryDelta != null && projContext.getOid() != null) {
secondaryDelta.setOid(projContext.getOid());
}
// result.computeStatus();
// // if the result is fatal error, it may mean that the
// // already exists expection occures before..but in this
// // scenario it means, the exception was handled and we
// // can mute the result to give better understanding of
// // the situation which happend
// if (result.isError()){
// result.muteError();
// }
// Re-do this same iteration again (do not increase iteration count).
// It will recompute the values and therefore enforce the user deltas and enable reconciliation
// to avoid endless loop
skipUniquenessCheck = true;
continue;
}
if (focus == null) {
LOGGER.trace("There is no owner linked with the conflicting projection.");
ResourceType resourceType = projContext.getResource();
if (ResourceTypeUtil.isSynchronizationOpportunistic(resourceType)) {
LOGGER.trace("Trying to find owner using correlation expression.");
boolean match = synchronizationService.matchUserCorrelationRule(fullConflictingShadow, context.getFocusContext().getObjectNew(), resourceType, context.getSystemConfiguration(), task, result);
if (match) {
if (projContext.getPrimaryDelta() != null && projContext.getPrimaryDelta().isAdd()) {
PrismObject<ShadowType> shadow = projContext.getPrimaryDelta().getObjectToAdd();
LOGGER.trace("Found primary ADD delta of shadow {}.", shadow);
LensProjectionContext conflictingAccountContext = context.findProjectionContext(projContext.getResourceShadowDiscriminator(), fullConflictingShadow.getOid());
if (conflictingAccountContext == null) {
conflictingAccountContext = LensUtil.createAccountContext(context, projContext.getResourceShadowDiscriminator());
// conflictingAccountContext = context.createProjectionContext(accountContext.getResourceShadowDiscriminator());
conflictingAccountContext.setOid(fullConflictingShadow.getOid());
conflictingAccountContext.setObjectOld(fullConflictingShadow.clone());
conflictingAccountContext.setObjectCurrent(fullConflictingShadow);
conflictingAccountContext.setFullShadow(true);
conflictingAccountContext.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.KEEP);
conflictingAccountContext.setResource(projContext.getResource());
conflictingAccountContext.setDoReconciliation(true);
conflictingAccountContext.getDependencies().clear();
conflictingAccountContext.getDependencies().addAll(projContext.getDependencies());
conflictingAccountContext.setWave(projContext.getWave());
context.addConflictingProjectionContext(conflictingAccountContext);
}
projContext.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.BROKEN);
result.recordFatalError("Could not add account " + projContext.getObjectNew() + ", because the account with the same identifier already exists on the resource. ");
LOGGER.error("Could not add account {}, because the account with the same identifier already exists on the resource. ", projContext.getObjectNew());
// to avoid endless loop
skipUniquenessCheck = true;
continue;
}
//found shadow belongs to the current user..need to link it and replace current shadow with the found shadow..
cleanupContext(projContext);
projContext.setObjectOld(fullConflictingShadow.clone());
projContext.setObjectCurrent(fullConflictingShadow);
projContext.setFullShadow(true);
projContext.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.KEEP);
ObjectDelta<ShadowType> secondaryDelta = projContext.getSecondaryDelta();
if (secondaryDelta != null && projContext.getOid() != null) {
secondaryDelta.setOid(projContext.getOid());
}
LOGGER.trace("User {} satisfies correlation rules.", context.getFocusContext().getObjectNew());
// Re-do this same iteration again (do not increase iteration count).
// It will recompute the values and therefore enforce the user deltas and enable reconciliation
// to avoid endless loop
skipUniquenessCheck = true;
continue;
} else {
LOGGER.trace("User {} does not satisfy correlation rules.", context.getFocusContext().getObjectNew());
}
}
} else {
LOGGER.trace("Recomputing shadow identifier, because shadow with the some identifier exists and it belongs to other user.");
}
}
}
}
}
if (!conflict) {
if (evaluateIterationCondition(context, projContext, iteration, iterationToken, false, task, result)) {
// stop the iterations
break;
} else {
conflictMessage = "post-iteration condition was false";
LOGGER.debug("Skipping iteration {}, token '{}' for {} because the post-iteration condition was false", new Object[] { iteration, iterationToken, projContext.getHumanReadableName() });
}
} else {
conflictMessage = checker.getMessages();
}
}
iteration++;
iterationToken = null;
LensUtil.checkMaxIterations(iteration, maxIterations, conflictMessage, projContext.getHumanReadableName());
cleanupContext(projContext);
if (consistencyChecks)
context.checkConsistence();
}
addIterationTokenDeltas(projContext);
result.cleanupResult();
if (consistencyChecks)
context.checkConsistence();
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.PartialProcessingTypeType.SKIP 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.xml.ns._public.common.common_3.PartialProcessingTypeType.SKIP in project midpoint by Evolveum.
the class TestSanityLegacy method test400ImportFromResource.
@Test
public void test400ImportFromResource() throws Exception {
final String TEST_NAME = "test400ImportFromResource";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
checkAllShadows();
assertNoRepoCache();
OperationResult result = new OperationResult(TestSanityLegacy.class.getName() + "." + TEST_NAME);
// Make sure Mr. Gibbs has "l" attribute set to the same value as an outbound expression is setting
ChangeRecordEntry entry = openDJController.executeLdifChange(LDIF_GIBBS_MODIFY_FILE);
display("Entry from LDIF", entry);
// Let's add an entry with multiple uids.
Entry addEntry = openDJController.addEntryFromLdifFile(LDIF_HERMAN_FILENAME);
display("Entry from LDIF", addEntry);
// WHEN
TaskType taskType = modelWeb.importFromResource(RESOURCE_OPENDJ_OID, IMPORT_OBJECTCLASS);
// THEN
assertNoRepoCache();
displayJaxb("importFromResource result", taskType.getResult(), SchemaConstants.C_RESULT);
AssertJUnit.assertEquals("importFromResource has failed", OperationResultStatusType.IN_PROGRESS, taskType.getResult().getStatus());
// Convert the returned TaskType to a more usable Task
Task task = taskManager.createTaskInstance(taskType.asPrismObject(), result);
AssertJUnit.assertNotNull(task);
assertNotNull(task.getOid());
AssertJUnit.assertTrue(task.isAsynchronous());
AssertJUnit.assertEquals(TaskExecutionStatus.RUNNABLE, task.getExecutionStatus());
// AssertJUnit.assertEquals(TaskExclusivityStatus.CLAIMED, task.getExclusivityStatus());
display("Import task after launch", task);
PrismObject<TaskType> tObject = repositoryService.getObject(TaskType.class, task.getOid(), null, result);
TaskType taskAfter = tObject.asObjectable();
display("Import task in repo after launch", taskAfter);
result.computeStatus();
TestUtil.assertSuccess("getObject has failed", result);
final String taskOid = task.getOid();
waitFor("Waiting for import to complete", new Checker() {
@Override
public boolean check() throws CommonException {
Holder<OperationResultType> resultHolder = new Holder<OperationResultType>();
Holder<ObjectType> objectHolder = new Holder<ObjectType>();
OperationResult opResult = new OperationResult("import check");
assertNoRepoCache();
SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType();
try {
modelWeb.getObject(ObjectTypes.TASK.getTypeQName(), taskOid, options, objectHolder, resultHolder);
} catch (FaultMessage faultMessage) {
throw new SystemException(faultMessage);
}
assertNoRepoCache();
// display("getObject result (wait loop)",resultHolder.value);
TestUtil.assertSuccess("getObject has failed", resultHolder.value);
Task task = taskManager.createTaskInstance((PrismObject<TaskType>) objectHolder.value.asPrismObject(), opResult);
System.out.println(new Date() + ": Import task status: " + task.getExecutionStatus() + ", progress: " + task.getProgress());
if (task.getExecutionStatus() == TaskExecutionStatus.CLOSED) {
// Task closed, wait finished
return true;
}
// IntegrationTestTools.display("Task result while waiting: ", task.getResult());
return false;
}
@Override
public void timeout() {
// No reaction, the test will fail right after return from this
}
}, 180000);
// wait a second until the task will be definitely saved
Thread.sleep(1000);
//### Check task state after the task is finished ###
Holder<ObjectType> objectHolder = new Holder<ObjectType>();
Holder<OperationResultType> resultHolder = new Holder<OperationResultType>();
SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType();
assertNoRepoCache();
modelWeb.getObject(ObjectTypes.TASK.getTypeQName(), task.getOid(), options, objectHolder, resultHolder);
assertNoRepoCache();
TestUtil.assertSuccess("getObject has failed", resultHolder.value);
task = taskManager.createTaskInstance((PrismObject<TaskType>) objectHolder.value.asPrismObject(), result);
display("Import task after finish (fetched from model)", task);
AssertJUnit.assertEquals(TaskExecutionStatus.CLOSED, task.getExecutionStatus());
assertNotNull("Null lastRunStartTimestamp in " + task, task.getLastRunStartTimestamp());
assertNotNull("Null lastRunFinishTimestamp in " + task, task.getLastRunFinishTimestamp());
long importDuration = task.getLastRunFinishTimestamp() - task.getLastRunStartTimestamp();
double usersPerSec = (task.getProgress() * 1000) / importDuration;
display("Imported " + task.getProgress() + " users in " + importDuration + " milliseconds (" + usersPerSec + " users/sec)");
OperationResult taskResult = task.getResult();
AssertJUnit.assertNotNull("Task has no result", taskResult);
TestUtil.assertSuccess("Import task result is not success", taskResult);
AssertJUnit.assertTrue("Task failed", taskResult.isSuccess());
AssertJUnit.assertTrue("No progress", task.getProgress() > 0);
//### Check if the import created users and shadows ###
// Listing of shadows is not supported by the provisioning. So we need
// to look directly into repository
List<PrismObject<ShadowType>> sobjects = repositoryService.searchObjects(ShadowType.class, null, null, result);
result.computeStatus();
TestUtil.assertSuccess("listObjects has failed", result);
AssertJUnit.assertFalse("No shadows created", sobjects.isEmpty());
for (PrismObject<ShadowType> aObject : sobjects) {
ShadowType shadow = aObject.asObjectable();
display("Shadow object after import (repo)", shadow);
// This would be really strange ;-)
assertNotEmpty("No OID in shadow", shadow.getOid());
assertNotEmpty("No name in shadow", shadow.getName());
AssertJUnit.assertNotNull("No objectclass in shadow", shadow.getObjectClass());
AssertJUnit.assertNotNull("Null attributes in shadow", shadow.getAttributes());
assertAttributeNotNull("No UID in shadow", shadow, SchemaConstants.ICFS_UID);
}
Holder<ObjectListType> listHolder = new Holder<ObjectListType>();
assertNoRepoCache();
modelWeb.searchObjects(ObjectTypes.USER.getTypeQName(), null, null, listHolder, resultHolder);
assertNoRepoCache();
ObjectListType uobjects = listHolder.value;
TestUtil.assertSuccess("listObjects has failed", resultHolder.value);
AssertJUnit.assertFalse("No users created", uobjects.getObject().isEmpty());
// TODO: use another account, not guybrush
display("Users after import " + uobjects.getObject().size());
for (ObjectType oo : uobjects.getObject()) {
UserType user = (UserType) oo;
if (SystemObjectsType.USER_ADMINISTRATOR.value().equals(user.getOid())) {
//skip administrator check
continue;
}
display("User after import (repo)", user);
// This would be
assertNotEmpty("No OID in user", user.getOid());
// really
// strange ;-)
assertNotEmpty("No name in user", user.getName());
assertNotNull("No fullName in user", user.getFullName());
assertNotEmpty("No fullName in user", user.getFullName().getOrig());
assertNotEmpty("No familyName in user", user.getFamilyName().getOrig());
if (user.getName().getOrig().equals(USER_GUYBRUSH_USERNAME)) {
// skip the rest of checks for guybrush, he does not have LDAP account now
continue;
}
assertTrue("User " + user.getName() + " is disabled (" + user.getActivation().getAdministrativeStatus() + ")", user.getActivation() == null || user.getActivation().getAdministrativeStatus() == ActivationStatusType.ENABLED);
List<ObjectReferenceType> accountRefs = user.getLinkRef();
AssertJUnit.assertEquals("Wrong accountRef for user " + user.getName(), 1, accountRefs.size());
ObjectReferenceType accountRef = accountRefs.get(0);
boolean found = false;
for (PrismObject<ShadowType> aObject : sobjects) {
ShadowType acc = aObject.asObjectable();
if (accountRef.getOid().equals(acc.getOid())) {
found = true;
break;
}
}
if (!found) {
AssertJUnit.fail("accountRef does not point to existing account " + accountRef.getOid());
}
PrismObject<ShadowType> aObject = modelService.getObject(ShadowType.class, accountRef.getOid(), null, task, result);
ShadowType account = aObject.asObjectable();
display("Account after import ", account);
String attributeValueL = ShadowUtil.getMultiStringAttributeValueAsSingle(account, new QName(ResourceTypeUtil.getResourceNamespace(resourceTypeOpenDjrepo), "l"));
// assertEquals("Unexcpected value of l", "middle of nowhere", attributeValueL);
assertEquals("Unexcpected value of l", getUserLocality(user), attributeValueL);
}
// This also includes "idm" user imported from LDAP. Later we need to ignore that one.
assertEquals("Wrong number of users after import", 10, uobjects.getObject().size());
checkAllShadows();
}
Aggregations