use of com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType in project midpoint by Evolveum.
the class ShadowIntegrityCheckResultHandler method checkShadow.
private void checkShadow(ShadowCheckResult checkResult, PrismObject<ShadowType> shadow, Task workerTask, OperationResult result) throws SchemaException {
ShadowType shadowType = shadow.asObjectable();
ObjectReferenceType resourceRef = shadowType.getResourceRef();
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Checking shadow {} (resource {})", ObjectTypeUtil.toShortString(shadowType), resourceRef != null ? resourceRef.getOid() : "(null)");
}
statistics.incrementShadows();
if (resourceRef == null) {
checkResult.recordError(Statistics.NO_RESOURCE_OID, new SchemaException("No resourceRef"));
fixNoResourceIfRequested(checkResult, Statistics.NO_RESOURCE_OID);
applyFixes(checkResult, shadow, workerTask, result);
return;
}
String resourceOid = resourceRef.getOid();
if (resourceOid == null) {
checkResult.recordError(Statistics.NO_RESOURCE_OID, new SchemaException("Null resource OID"));
fixNoResourceIfRequested(checkResult, Statistics.NO_RESOURCE_OID);
applyFixes(checkResult, shadow, workerTask, result);
return;
}
PrismObject<ResourceType> resource = resources.get(resourceOid);
if (resource == null) {
statistics.incrementResources();
try {
resource = provisioningService.getObject(ResourceType.class, resourceOid, null, workerTask, result);
} catch (ObjectNotFoundException e) {
checkResult.recordError(Statistics.NO_RESOURCE, new ObjectNotFoundException("Resource object does not exist: " + e.getMessage(), e));
fixNoResourceIfRequested(checkResult, Statistics.NO_RESOURCE);
applyFixes(checkResult, shadow, workerTask, result);
return;
} catch (SchemaException e) {
checkResult.recordError(Statistics.CANNOT_GET_RESOURCE, new SchemaException("Resource object has schema problems: " + e.getMessage(), e));
return;
} catch (CommonException | RuntimeException e) {
checkResult.recordError(Statistics.CANNOT_GET_RESOURCE, new SystemException("Resource object cannot be fetched for some reason: " + e.getMessage(), e));
return;
}
resources.put(resourceOid, resource);
}
checkResult.setResource(resource);
ShadowKindType kind = shadowType.getKind();
if (kind == null) {
// TODO or simply assume account?
checkResult.recordError(Statistics.NO_KIND_SPECIFIED, new SchemaException("No kind specified"));
return;
}
if (checkExtraData) {
checkOrFixShadowActivationConsistency(checkResult, shadow, fixExtraData);
}
PrismObject<ShadowType> fetchedShadow = null;
if (checkFetch) {
fetchedShadow = fetchShadow(checkResult, shadow, resource, workerTask, result);
if (fetchedShadow != null) {
shadow.setUserData(KEY_EXISTS_ON_RESOURCE, "true");
}
}
if (checkOwners) {
List<PrismObject<FocusType>> owners = searchOwners(shadow, result);
if (owners != null) {
shadow.setUserData(KEY_OWNERS, owners);
if (owners.size() > 1) {
checkResult.recordError(Statistics.MULTIPLE_OWNERS, new SchemaException("Multiple owners: " + owners));
}
}
if (shadowType.getSynchronizationSituation() == SynchronizationSituationType.LINKED && (owners == null || owners.isEmpty())) {
checkResult.recordError(Statistics.LINKED_WITH_NO_OWNER, new SchemaException("Linked shadow with no owner"));
}
if (shadowType.getSynchronizationSituation() != SynchronizationSituationType.LINKED && owners != null && !owners.isEmpty()) {
checkResult.recordError(Statistics.NOT_LINKED_WITH_OWNER, new SchemaException("Shadow with an owner but not marked as linked (marked as " + shadowType.getSynchronizationSituation() + ")"));
}
}
String intent = shadowType.getIntent();
if (checkIntents && (intent == null || intent.isEmpty())) {
checkResult.recordWarning(Statistics.NO_INTENT_SPECIFIED, "None or empty intent");
}
if (fixIntents && (intent == null || intent.isEmpty())) {
doFixIntent(checkResult, fetchedShadow, shadow, resource, workerTask, result);
}
Pair<String, ShadowKindType> key = new ImmutablePair<>(resourceOid, kind);
ObjectTypeContext context = contextMap.get(key);
if (context == null) {
context = new ObjectTypeContext();
context.setResource(resource);
RefinedResourceSchema resourceSchema;
try {
resourceSchema = RefinedResourceSchemaImpl.getRefinedSchema(context.getResource(), LayerType.MODEL, prismContext);
} catch (SchemaException e) {
checkResult.recordError(Statistics.CANNOT_GET_REFINED_SCHEMA, new SchemaException("Couldn't derive resource schema: " + e.getMessage(), e));
return;
}
if (resourceSchema == null) {
checkResult.recordError(Statistics.NO_RESOURCE_REFINED_SCHEMA, new SchemaException("No resource schema"));
return;
}
context.setObjectClassDefinition(resourceSchema.getRefinedDefinition(kind, shadowType));
if (context.getObjectClassDefinition() == null) {
// TODO or warning only?
checkResult.recordError(Statistics.NO_OBJECT_CLASS_REFINED_SCHEMA, new SchemaException("No refined object class definition for kind=" + kind + ", intent=" + intent));
return;
}
contextMap.put(key, context);
}
try {
provisioningService.applyDefinition(shadow, workerTask, result);
} catch (SchemaException | ObjectNotFoundException | CommunicationException | ConfigurationException | ExpressionEvaluationException e) {
checkResult.recordError(Statistics.OTHER_FAILURE, new SystemException("Couldn't apply definition to shadow from repo", e));
return;
}
Set<RefinedAttributeDefinition<?>> identifiers = new HashSet<>();
Collection<? extends RefinedAttributeDefinition<?>> primaryIdentifiers = context.getObjectClassDefinition().getPrimaryIdentifiers();
identifiers.addAll(primaryIdentifiers);
identifiers.addAll(context.getObjectClassDefinition().getSecondaryIdentifiers());
PrismContainer<ShadowAttributesType> attributesContainer = shadow.findContainer(ShadowType.F_ATTRIBUTES);
if (attributesContainer == null) {
// might happen on unfinished shadows?
checkResult.recordError(Statistics.OTHER_FAILURE, new SchemaException("No attributes container"));
return;
}
for (RefinedAttributeDefinition<?> identifier : identifiers) {
PrismProperty property = attributesContainer.getValue().findProperty(identifier.getName());
if (property == null || property.size() == 0) {
checkResult.recordWarning(Statistics.OTHER_FAILURE, "No value for identifier " + identifier.getName());
continue;
}
if (property.size() > 1) {
// we don't expect multi-valued identifiers
checkResult.recordError(Statistics.OTHER_FAILURE, new SchemaException("Multi-valued identifier " + identifier.getName() + " with values " + property.getValues()));
continue;
}
// size == 1
String value = (String) property.getValue().getValue();
if (value == null) {
checkResult.recordWarning(Statistics.OTHER_FAILURE, "Null value for identifier " + identifier.getName());
continue;
}
if (checkUniqueness) {
if (!checkDuplicatesOnPrimaryIdentifiersOnly || primaryIdentifiers.contains(identifier)) {
addIdentifierValue(checkResult, context, identifier.getName(), value, shadow);
}
}
if (checkNormalization) {
doCheckNormalization(checkResult, identifier, value, context);
}
}
applyFixes(checkResult, shadow, workerTask, result);
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType in project midpoint by Evolveum.
the class ShadowIntegrityCheckResultHandler method deleteShadows.
// shadowsToDelete do not contain 'already deleted shadows'
private void deleteShadows(DuplicateShadowsTreatmentInstruction instruction, StringBuilder sb, Task task, OperationResult result) {
LOGGER.trace("Going to delete shadows:\n{}", instruction);
if (instruction == null || instruction.getShadowsToDelete() == null) {
return;
}
Collection<PrismObject<ShadowType>> shadowsToDelete = instruction.getShadowsToDelete();
String shadowOidToReplaceDeleted = instruction.getShadowOidToReplaceDeletedOnes();
for (PrismObject<ShadowType> shadowToDelete : shadowsToDelete) {
LOGGER.info("Deleting redundant shadow{} {}", skippedForDryRun(), ObjectTypeUtil.toShortString(shadowToDelete));
sb.append(" --> deleted redundant shadow").append(skippedForDryRun()).append(" ").append(ObjectTypeUtil.toShortString(shadowToDelete)).append("\n");
String oid = shadowToDelete.getOid();
List<PrismObject<FocusType>> owners;
if (checkOwners) {
owners = (List) shadowToDelete.getUserData(KEY_OWNERS);
} else {
owners = searchOwners(shadowToDelete, result);
}
if (!dryRun) {
try {
repositoryService.deleteObject(ShadowType.class, oid, result);
task.recordObjectActionExecuted(shadowToDelete, ChangeType.DELETE, null);
duplicateShadowsDeleted.add(oid);
} catch (ObjectNotFoundException e) {
// suspicious, but not a big deal
task.recordObjectActionExecuted(shadowToDelete, ChangeType.DELETE, e);
LoggingUtils.logExceptionAsWarning(LOGGER, "Shadow {} couldn't be deleted, because it does not exist anymore", e, ObjectTypeUtil.toShortString(shadowToDelete));
continue;
} catch (RuntimeException e) {
task.recordObjectActionExecuted(shadowToDelete, ChangeType.DELETE, e);
LoggingUtils.logUnexpectedException(LOGGER, "Shadow {} couldn't be deleted because of an unexpected exception", e, ObjectTypeUtil.toShortString(shadowToDelete));
continue;
}
}
if (owners == null || owners.isEmpty()) {
continue;
}
for (PrismObject owner : owners) {
List<ItemDelta> modifications = new ArrayList<>(2);
ReferenceDelta deleteDelta = ReferenceDelta.createModificationDelete(FocusType.F_LINK_REF, owner.getDefinition(), new PrismReferenceValue(oid, ShadowType.COMPLEX_TYPE));
modifications.add(deleteDelta);
if (shadowOidToReplaceDeleted != null) {
ReferenceDelta addDelta = ReferenceDelta.createModificationAdd(FocusType.F_LINK_REF, owner.getDefinition(), new PrismReferenceValue(shadowOidToReplaceDeleted, ShadowType.COMPLEX_TYPE));
modifications.add(addDelta);
}
LOGGER.info("Executing modify delta{} for owner {}:\n{}", skippedForDryRun(), ObjectTypeUtil.toShortString(owner), DebugUtil.debugDump(modifications));
if (!dryRun) {
try {
repositoryService.modifyObject((Class) owner.getClass(), owner.getOid(), modifications, result);
task.recordObjectActionExecuted(owner, ChangeType.MODIFY, null);
} catch (ObjectNotFoundException | SchemaException | ObjectAlreadyExistsException | RuntimeException e) {
task.recordObjectActionExecuted(owner, ChangeType.MODIFY, e);
LoggingUtils.logUnexpectedException(LOGGER, "Focal object {} (owner of {}) couldn't be updated", e, ObjectTypeUtil.toShortString(owner), ObjectTypeUtil.toShortString(shadowToDelete));
}
}
}
}
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType in project midpoint by Evolveum.
the class ShadowIntegrityCheckResultHandler method searchOwners.
private List<PrismObject<FocusType>> searchOwners(PrismObject<ShadowType> shadow, OperationResult result) {
try {
ObjectQuery ownerQuery = QueryBuilder.queryFor(FocusType.class, prismContext).item(FocusType.F_LINK_REF).ref(shadow.getOid()).build();
List<PrismObject<FocusType>> owners = repositoryService.searchObjects(FocusType.class, ownerQuery, null, result);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Owners for {}: {}", ObjectTypeUtil.toShortString(shadow), owners);
}
return owners;
} catch (SchemaException | RuntimeException e) {
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't create/execute owners query for shadow {}", e, ObjectTypeUtil.toShortString(shadow));
return null;
}
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType in project midpoint by Evolveum.
the class ShadowIntegrityCheckResultHandler method checkOrFixShadowActivationConsistency.
// adapted from ProvisioningUtil
public void checkOrFixShadowActivationConsistency(ShadowCheckResult checkResult, PrismObject<ShadowType> shadow, boolean fix) {
if (shadow == null) {
// just for sure
return;
}
ActivationType activation = shadow.asObjectable().getActivation();
if (activation == null) {
return;
}
FailedOperationTypeType failedOperation = shadow.asObjectable().getFailedOperationType();
if (failedOperation == FailedOperationTypeType.ADD) {
// in this case it's ok to have activation present
return;
}
checkOrFixActivationItem(checkResult, shadow, activation.asPrismContainerValue(), ActivationType.F_ADMINISTRATIVE_STATUS);
checkOrFixActivationItem(checkResult, shadow, activation.asPrismContainerValue(), ActivationType.F_EFFECTIVE_STATUS);
checkOrFixActivationItem(checkResult, shadow, activation.asPrismContainerValue(), ActivationType.F_VALID_FROM);
checkOrFixActivationItem(checkResult, shadow, activation.asPrismContainerValue(), ActivationType.F_VALID_TO);
checkOrFixActivationItem(checkResult, shadow, activation.asPrismContainerValue(), ActivationType.F_VALIDITY_STATUS);
checkOrFixActivationItem(checkResult, shadow, activation.asPrismContainerValue(), ActivationType.F_VALIDITY_CHANGE_TIMESTAMP);
checkOrFixActivationItem(checkResult, shadow, activation.asPrismContainerValue(), ActivationType.F_LOCKOUT_STATUS);
checkOrFixActivationItem(checkResult, shadow, activation.asPrismContainerValue(), ActivationType.F_LOCKOUT_EXPIRATION_TIMESTAMP);
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType in project midpoint by Evolveum.
the class ShadowIntegrityCheckResultHandler method addIdentifierValue.
private void addIdentifierValue(ShadowCheckResult checkResult, ObjectTypeContext context, QName identifierName, String identifierValue, PrismObject<ShadowType> shadow) {
Map<String, List<PrismObject<ShadowType>>> valueMap = context.getIdentifierValueMap().get(identifierName);
if (valueMap == null) {
valueMap = new HashMap<>();
context.getIdentifierValueMap().put(identifierName, valueMap);
}
List<PrismObject<ShadowType>> existingShadows = valueMap.get(identifierValue);
if (existingShadows == null) {
// all is well
existingShadows = new ArrayList();
existingShadows.add(shadow);
valueMap.put(identifierValue, existingShadows);
} else {
// duplicate shadows statistics are collected in a special way
duplicateShadowsDetected.add(shadow.getOid());
LOGGER.error("Multiple shadows with the value of identifier attribute {} = {}: existing one(s): {}, duplicate: {}", identifierName, identifierValue, shortDumpList(existingShadows), ObjectTypeUtil.toShortString(shadow.asObjectable()));
existingShadows.add(shadow);
}
}
Aggregations