Search in sources :

Example 6 with GenericConnectorException

use of com.evolveum.midpoint.provisioning.api.GenericConnectorException in project midpoint by Evolveum.

the class ResourceObjectConverter method addResourceObject.

public AsynchronousOperationReturnValue<PrismObject<ShadowType>> addResourceObject(ProvisioningContext ctx, PrismObject<ShadowType> shadow, OperationProvisioningScriptsType scripts, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, ObjectAlreadyExistsException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
    OperationResult result = parentResult.createSubresult(OPERATION_ADD_RESOURCE_OBJECT);
    ResourceType resource = ctx.getResource();
    LOGGER.trace("Adding resource object {}", shadow);
    // We might be modifying the shadow (e.g. for simulated capabilities). But we do not want the changes
    // to propagate back to the calling code. Hence the clone.
    PrismObject<ShadowType> shadowClone = shadow.clone();
    ShadowType shadowType = shadowClone.asObjectable();
    Collection<ResourceAttribute<?>> resourceAttributesAfterAdd = null;
    if (ProvisioningUtil.isProtectedShadow(ctx.getObjectClassDefinition(), shadowClone, matchingRuleRegistry)) {
        LOGGER.error("Attempt to add protected shadow " + shadowType + "; ignoring the request");
        SecurityViolationException e = new SecurityViolationException("Cannot get protected shadow " + shadowType);
        result.recordFatalError(e);
        throw e;
    }
    Collection<Operation> additionalOperations = new ArrayList<Operation>();
    addExecuteScriptOperation(additionalOperations, ProvisioningOperationTypeType.ADD, scripts, resource, result);
    entitlementConverter.processEntitlementsAdd(ctx, shadowClone);
    ConnectorInstance connector = ctx.getConnector(CreateCapabilityType.class, result);
    try {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("PROVISIONING ADD operation on resource {}\n ADD object:\n{}\n additional operations:\n{}", resource.asPrismObject(), shadowType.asPrismObject().debugDump(), SchemaDebugUtil.debugDump(additionalOperations, 2));
        }
        transformActivationAttributesAdd(ctx, shadowType, result);
        if (!ResourceTypeUtil.isCreateCapabilityEnabled(resource)) {
            throw new UnsupportedOperationException("Resource does not support 'create' operation");
        }
        AsynchronousOperationReturnValue<Collection<ResourceAttribute<?>>> ret = connector.addObject(shadowClone, additionalOperations, ctx, result);
        resourceAttributesAfterAdd = ret.getReturnValue();
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("PROVISIONING ADD successful, returned attributes:\n{}", SchemaDebugUtil.prettyPrint(resourceAttributesAfterAdd));
        }
        // Be careful not to apply this to the cloned shadow. This needs to be propagated
        // outside this method.
        applyAfterOperationAttributes(shadow, resourceAttributesAfterAdd);
    } catch (CommunicationException ex) {
        result.recordFatalError("Could not create object on the resource. Error communicating with the connector " + connector + ": " + ex.getMessage(), ex);
        throw new CommunicationException("Error communicating with the connector " + connector + ": " + ex.getMessage(), ex);
    } catch (GenericFrameworkException ex) {
        result.recordFatalError("Could not create object on the resource. Generic error in connector: " + ex.getMessage(), ex);
        throw new GenericConnectorException("Generic error in connector: " + ex.getMessage(), ex);
    } catch (ObjectAlreadyExistsException ex) {
        result.recordFatalError("Could not create object on the resource. Object already exists on the resource: " + ex.getMessage(), ex);
        throw new ObjectAlreadyExistsException("Object already exists on the resource: " + ex.getMessage(), ex);
    } catch (ConfigurationException | SchemaException | RuntimeException | Error e) {
        result.recordFatalError(e);
        throw e;
    }
    // Execute entitlement modification on other objects (if needed)
    executeEntitlementChangesAdd(ctx, shadowClone, scripts, result);
    LOGGER.trace("Added resource object {}", shadow);
    computeResultStatus(result);
    return AsynchronousOperationReturnValue.wrap(shadow, result);
}
Also used : OperationResult(com.evolveum.midpoint.schema.result.OperationResult) AsynchronousOperationResult(com.evolveum.midpoint.schema.result.AsynchronousOperationResult) GenericConnectorException(com.evolveum.midpoint.provisioning.api.GenericConnectorException)

Example 7 with GenericConnectorException

use of com.evolveum.midpoint.provisioning.api.GenericConnectorException in project midpoint by Evolveum.

the class ResourceObjectConverter method executeModify.

private Collection<PropertyModificationOperation> executeModify(ProvisioningContext ctx, PrismObject<ShadowType> currentShadow, Collection<? extends ResourceAttribute<?>> identifiers, Collection<Operation> operations, OperationResult parentResult) throws ObjectNotFoundException, CommunicationException, SchemaException, SecurityViolationException, ConfigurationException, ObjectAlreadyExistsException, ExpressionEvaluationException {
    Collection<PropertyModificationOperation> sideEffectChanges = new HashSet<>();
    RefinedObjectClassDefinition objectClassDefinition = ctx.getObjectClassDefinition();
    if (operations.isEmpty()) {
        LOGGER.trace("No modifications for resource object. Skipping modification.");
        return new ArrayList<>(0);
    } else {
        LOGGER.trace("Resource object modification operations: {}", operations);
    }
    if (!ShadowUtil.hasPrimaryIdentifier(identifiers, objectClassDefinition)) {
        Collection<? extends ResourceAttribute<?>> primaryIdentifiers = resourceObjectReferenceResolver.resolvePrimaryIdentifier(ctx, identifiers, "modification of resource object " + identifiers, parentResult);
        if (primaryIdentifiers == null || primaryIdentifiers.isEmpty()) {
            throw new ObjectNotFoundException("Cannot find repository shadow for identifiers " + identifiers);
        }
        identifiers = primaryIdentifiers;
    }
    // Invoke ICF
    ConnectorInstance connector = ctx.getConnector(UpdateCapabilityType.class, parentResult);
    try {
        if (ResourceTypeUtil.isAvoidDuplicateValues(ctx.getResource())) {
            if (currentShadow == null) {
                LOGGER.trace("Fetching shadow for duplicate filtering");
                currentShadow = preReadShadow(ctx, identifiers, operations, false, parentResult);
            }
            Collection<Operation> filteredOperations = new ArrayList(operations.size());
            for (Operation origOperation : operations) {
                if (origOperation instanceof PropertyModificationOperation) {
                    PropertyModificationOperation modificationOperation = (PropertyModificationOperation) origOperation;
                    PropertyDelta<?> propertyDelta = modificationOperation.getPropertyDelta();
                    PropertyDelta<?> filteredDelta = ProvisioningUtil.narrowPropertyDelta(propertyDelta, currentShadow, modificationOperation.getMatchingRuleQName(), matchingRuleRegistry);
                    if (filteredDelta != null && !filteredDelta.isEmpty()) {
                        if (propertyDelta == filteredDelta) {
                            filteredOperations.add(origOperation);
                        } else {
                            PropertyModificationOperation newOp = new PropertyModificationOperation(filteredDelta);
                            newOp.setMatchingRuleQName(modificationOperation.getMatchingRuleQName());
                            filteredOperations.add(newOp);
                        }
                    } else {
                        LOGGER.trace("Filtering out modification {} because it has empty delta after narrow", propertyDelta);
                    }
                } else if (origOperation instanceof ExecuteProvisioningScriptOperation) {
                    filteredOperations.add(origOperation);
                }
            }
            if (filteredOperations.isEmpty()) {
                LOGGER.debug("No modifications for connector object specified (after filtering). Skipping processing.");
                parentResult.recordSuccess();
                return new ArrayList<>(0);
            }
            operations = filteredOperations;
        }
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("PROVISIONING MODIFY operation on {}\n MODIFY object, object class {}, identified by:\n{}\n changes:\n{}", ctx.getResource(), objectClassDefinition.getHumanReadableName(), SchemaDebugUtil.debugDump(identifiers, 1), SchemaDebugUtil.debugDump(operations, 1));
        }
        if (!ResourceTypeUtil.isUpdateCapabilityEnabled(ctx.getResource())) {
            if (operations == null || operations.isEmpty()) {
                LOGGER.debug("No modifications for connector object specified (after filtering). Skipping processing.");
                parentResult.recordSuccess();
                return new ArrayList<>(0);
            }
            UnsupportedOperationException e = new UnsupportedOperationException("Resource does not support 'update' operation");
            parentResult.recordFatalError(e);
            throw e;
        }
        // because identifiers can be modified e.g. on rename operation
        Collection<ResourceAttribute<?>> identifiersWorkingCopy = cloneIdentifiers(identifiers);
        List<Collection<Operation>> operationsWaves = sortOperationsIntoWaves(operations, objectClassDefinition);
        LOGGER.trace("Operation waves: {}", operationsWaves.size());
        boolean inProgress = false;
        String asyncronousOperationReference = null;
        for (Collection<Operation> operationsWave : operationsWaves) {
            Collection<RefinedAttributeDefinition> readReplaceAttributes = determineReadReplace(operationsWave, objectClassDefinition);
            LOGGER.trace("Read+Replace attributes: {}", readReplaceAttributes);
            if (!readReplaceAttributes.isEmpty()) {
                AttributesToReturn attributesToReturn = new AttributesToReturn();
                attributesToReturn.setReturnDefaultAttributes(false);
                attributesToReturn.setAttributesToReturn(readReplaceAttributes);
                // TODO eliminate this fetch if this is first wave and there are no explicitly requested attributes
                // but make sure currentShadow contains all required attributes
                LOGGER.trace("Fetching object because of READ+REPLACE mode");
                currentShadow = fetchResourceObject(ctx, identifiersWorkingCopy, attributesToReturn, false, parentResult);
                operationsWave = convertToReplace(ctx, operationsWave, currentShadow);
            }
            if (!operationsWave.isEmpty()) {
                AsynchronousOperationReturnValue<Collection<PropertyModificationOperation>> ret = connector.modifyObject(objectClassDefinition, identifiersWorkingCopy, operationsWave, ctx, parentResult);
                Collection<PropertyModificationOperation> sideEffects = ret.getReturnValue();
                if (sideEffects != null) {
                    sideEffectChanges.addAll(sideEffects);
                // we accept that one attribute can be changed multiple times in sideEffectChanges; TODO: normalize
                }
                if (ret.isInProgress()) {
                    inProgress = true;
                    asyncronousOperationReference = ret.getOperationResult().getAsynchronousOperationReference();
                }
            }
        }
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("PROVISIONING MODIFY successful, inProgress={}, side-effect changes {}", inProgress, DebugUtil.debugDump(sideEffectChanges));
        }
        if (inProgress) {
            parentResult.recordInProgress();
            parentResult.setAsynchronousOperationReference(asyncronousOperationReference);
        }
    } catch (ObjectNotFoundException ex) {
        parentResult.recordFatalError("Object to modify not found: " + ex.getMessage(), ex);
        throw new ObjectNotFoundException("Object to modify not found: " + ex.getMessage(), ex);
    } catch (CommunicationException ex) {
        parentResult.recordFatalError("Error communicating with the connector " + connector + ": " + ex.getMessage(), ex);
        throw new CommunicationException("Error communicating with connector " + connector + ": " + ex.getMessage(), ex);
    } catch (SchemaException ex) {
        parentResult.recordFatalError("Schema violation: " + ex.getMessage(), ex);
        throw new SchemaException("Schema violation: " + ex.getMessage(), ex);
    } catch (SecurityViolationException ex) {
        parentResult.recordFatalError("Security violation: " + ex.getMessage(), ex);
        throw new SecurityViolationException("Security violation: " + ex.getMessage(), ex);
    } catch (GenericFrameworkException ex) {
        parentResult.recordFatalError("Generic error in the connector " + connector + ": " + ex.getMessage(), ex);
        throw new GenericConnectorException("Generic error in connector connector " + connector + ": " + ex.getMessage(), ex);
    } catch (ConfigurationException ex) {
        parentResult.recordFatalError("Configuration error: " + ex.getMessage(), ex);
        throw ex;
    } catch (ExpressionEvaluationException ex) {
        parentResult.recordFatalError("Configuration error: " + ex.getMessage(), ex);
        throw ex;
    } catch (ObjectAlreadyExistsException ex) {
        parentResult.recordFatalError("Conflict during modify: " + ex.getMessage(), ex);
        throw new ObjectAlreadyExistsException("Conflict during modify: " + ex.getMessage(), ex);
    }
    return sideEffectChanges;
}
Also used : GenericConnectorException(com.evolveum.midpoint.provisioning.api.GenericConnectorException)

Example 8 with GenericConnectorException

use of com.evolveum.midpoint.provisioning.api.GenericConnectorException in project midpoint by Evolveum.

the class ResourceObjectConverter method locateResourceObject.

/**
	 * Tries to get the object directly if primary identifiers are present. Tries to search for the object if they are not. 
	 */
public PrismObject<ShadowType> locateResourceObject(ProvisioningContext ctx, Collection<? extends ResourceAttribute<?>> identifiers, OperationResult parentResult) throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, GenericConnectorException, ExpressionEvaluationException {
    LOGGER.trace("Locating resource object {}", identifiers);
    ConnectorInstance connector = ctx.getConnector(ReadCapabilityType.class, parentResult);
    AttributesToReturn attributesToReturn = ProvisioningUtil.createAttributesToReturn(ctx);
    if (hasAllIdentifiers(identifiers, ctx.getObjectClassDefinition())) {
        return fetchResourceObject(ctx, identifiers, attributesToReturn, true, // todo consider whether it is always necessary to fetch the entitlements
        parentResult);
    } else {
        // Search
        Collection<? extends RefinedAttributeDefinition> secondaryIdentifierDefs = ctx.getObjectClassDefinition().getSecondaryIdentifiers();
        // Assume single secondary identifier for simplicity
        if (secondaryIdentifierDefs.size() > 1) {
            throw new UnsupportedOperationException("Composite secondary identifier is not supported yet");
        } else if (secondaryIdentifierDefs.isEmpty()) {
            throw new SchemaException("No secondary identifier defined, cannot search");
        }
        RefinedAttributeDefinition<String> secondaryIdentifierDef = secondaryIdentifierDefs.iterator().next();
        ResourceAttribute<?> secondaryIdentifier = null;
        for (ResourceAttribute<?> identifier : identifiers) {
            if (identifier.getElementName().equals(secondaryIdentifierDef.getName())) {
                secondaryIdentifier = identifier;
            }
        }
        if (secondaryIdentifier == null) {
            throw new SchemaException("No secondary identifier present, cannot search. Identifiers: " + identifiers);
        }
        final ResourceAttribute<?> finalSecondaryIdentifier = secondaryIdentifier;
        List<PrismPropertyValue<String>> secondaryIdentifierValues = (List) secondaryIdentifier.getValues();
        PrismPropertyValue<String> secondaryIdentifierValue;
        if (secondaryIdentifierValues.size() > 1) {
            throw new IllegalStateException("Secondary identifier has more than one value: " + secondaryIdentifier.getValues());
        } else if (secondaryIdentifierValues.size() == 1) {
            secondaryIdentifierValue = secondaryIdentifierValues.get(0).clone();
        } else {
            secondaryIdentifierValue = null;
        }
        ObjectQuery query = QueryBuilder.queryFor(ShadowType.class, prismContext).itemWithDef(secondaryIdentifierDef, ShadowType.F_ATTRIBUTES, secondaryIdentifierDef.getName()).eq(secondaryIdentifierValue).build();
        final Holder<PrismObject<ShadowType>> shadowHolder = new Holder<PrismObject<ShadowType>>();
        ResultHandler<ShadowType> handler = new ResultHandler<ShadowType>() {

            @Override
            public boolean handle(PrismObject<ShadowType> shadow) {
                if (!shadowHolder.isEmpty()) {
                    throw new IllegalStateException("More than one value found for secondary identifier " + finalSecondaryIdentifier);
                }
                shadowHolder.setValue(shadow);
                return true;
            }
        };
        try {
            connector.search(ctx.getObjectClassDefinition(), query, handler, attributesToReturn, null, null, ctx, parentResult);
            if (shadowHolder.isEmpty()) {
                throw new ObjectNotFoundException("No object found for secondary identifier " + secondaryIdentifier);
            }
            PrismObject<ShadowType> shadow = shadowHolder.getValue();
            PrismObject<ShadowType> finalShadow = postProcessResourceObjectRead(ctx, shadow, true, parentResult);
            LOGGER.trace("Located resource object {}", finalShadow);
            return finalShadow;
        } catch (GenericFrameworkException e) {
            throw new GenericConnectorException(e.getMessage(), e);
        }
    }
}
Also used : ObjectQuery(com.evolveum.midpoint.prism.query.ObjectQuery) GenericConnectorException(com.evolveum.midpoint.provisioning.api.GenericConnectorException)

Example 9 with GenericConnectorException

use of com.evolveum.midpoint.provisioning.api.GenericConnectorException in project midpoint by Evolveum.

the class ResourceObjectConverter method searchResourceObjects.

public SearchResultMetadata searchResourceObjects(final ProvisioningContext ctx, final ResultHandler<ShadowType> resultHandler, ObjectQuery query, final boolean fetchAssociations, final OperationResult parentResult) throws SchemaException, CommunicationException, ObjectNotFoundException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
    LOGGER.trace("Searching resource objects, query: {}", query);
    RefinedObjectClassDefinition objectClassDef = ctx.getObjectClassDefinition();
    AttributesToReturn attributesToReturn = ProvisioningUtil.createAttributesToReturn(ctx);
    SearchHierarchyConstraints searchHierarchyConstraints = null;
    ResourceObjectReferenceType baseContextRef = objectClassDef.getBaseContext();
    if (baseContextRef != null) {
        PrismObject<ShadowType> baseContextShadow = resourceObjectReferenceResolver.resolve(ctx, baseContextRef, null, "base context specification in " + objectClassDef, parentResult);
        if (baseContextShadow == null) {
            throw new ObjectNotFoundException("No base context defined by " + baseContextRef + " in base context specification in " + objectClassDef);
        }
        RefinedObjectClassDefinition baseContextObjectClassDefinition = ctx.getRefinedSchema().determineCompositeObjectClassDefinition(baseContextShadow);
        ResourceObjectIdentification baseContextIdentification = ShadowUtil.getResourceObjectIdentification(baseContextShadow, baseContextObjectClassDefinition);
        searchHierarchyConstraints = new SearchHierarchyConstraints(baseContextIdentification, null);
    }
    if (InternalsConfig.consistencyChecks && query != null && query.getFilter() != null) {
        query.getFilter().checkConsistence(true);
    }
    ConnectorInstance connector = ctx.getConnector(ReadCapabilityType.class, parentResult);
    SearchResultMetadata metadata = null;
    try {
        metadata = connector.search(objectClassDef, query, (shadow) -> {
            // in order to utilize the cache right from the beginning...
            RepositoryCache.enter();
            try {
                try {
                    shadow = postProcessResourceObjectRead(ctx, shadow, fetchAssociations, parentResult);
                } catch (SchemaException | CommunicationException | ConfigurationException | SecurityViolationException | ObjectNotFoundException | ExpressionEvaluationException e) {
                    throw new TunnelException(e);
                }
                return resultHandler.handle(shadow);
            } finally {
                RepositoryCache.exit();
            }
        }, attributesToReturn, objectClassDef.getPagedSearches(), searchHierarchyConstraints, ctx, parentResult);
    } catch (GenericFrameworkException e) {
        parentResult.recordFatalError("Generic error in the connector: " + e.getMessage(), e);
        throw new SystemException("Generic error in the connector: " + e.getMessage(), e);
    } catch (CommunicationException ex) {
        parentResult.recordFatalError("Error communicating with the connector " + connector + ": " + ex.getMessage(), ex);
        throw new CommunicationException("Error communicating with the connector " + connector + ": " + ex.getMessage(), ex);
    } catch (SecurityViolationException ex) {
        parentResult.recordFatalError("Security violation communicating with the connector " + connector + ": " + ex.getMessage(), ex);
        throw new SecurityViolationException("Security violation communicating with the connector " + connector + ": " + ex.getMessage(), ex);
    } catch (TunnelException e) {
        Throwable cause = e.getCause();
        if (cause instanceof SchemaException) {
            throw (SchemaException) cause;
        } else if (cause instanceof CommunicationException) {
            throw (CommunicationException) cause;
        } else if (cause instanceof ObjectNotFoundException) {
            throw (ObjectNotFoundException) cause;
        } else if (cause instanceof ConfigurationException) {
            throw (ConfigurationException) cause;
        } else if (cause instanceof SecurityViolationException) {
            throw (SecurityViolationException) cause;
        } else if (cause instanceof ExpressionEvaluationException) {
            throw (ExpressionEvaluationException) cause;
        } else if (cause instanceof GenericFrameworkException) {
            throw new GenericConnectorException(cause.getMessage(), cause);
        } else {
            throw new SystemException(cause.getMessage(), cause);
        }
    }
    computeResultStatus(parentResult);
    LOGGER.trace("Searching resource objects done: {}", parentResult.getStatus());
    return metadata;
}
Also used : StringUtils(org.apache.commons.lang.StringUtils) ActivationCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationCapabilityType) Autowired(org.springframework.beans.factory.annotation.Autowired) com.evolveum.midpoint.util.exception(com.evolveum.midpoint.util.exception) InternalsConfig(com.evolveum.midpoint.schema.internals.InternalsConfig) OperationResultStatus(com.evolveum.midpoint.schema.result.OperationResultStatus) com.evolveum.midpoint.common.refinery(com.evolveum.midpoint.common.refinery) AsynchronousOperationReturnValue(com.evolveum.midpoint.schema.result.AsynchronousOperationReturnValue) com.evolveum.midpoint.prism(com.evolveum.midpoint.prism) ObjectDelta(com.evolveum.midpoint.prism.delta.ObjectDelta) ResourceTypeUtil(com.evolveum.midpoint.schema.util.ResourceTypeUtil) MatchingRuleRegistry(com.evolveum.midpoint.prism.match.MatchingRuleRegistry) AsynchronousOperationQueryable(com.evolveum.midpoint.schema.result.AsynchronousOperationQueryable) ResourceShadowDiscriminator(com.evolveum.midpoint.schema.ResourceShadowDiscriminator) DeleteCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.DeleteCapabilityType) ReadCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ReadCapabilityType) UpdateCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.UpdateCapabilityType) Entry(java.util.Map.Entry) PropertyDelta(com.evolveum.midpoint.prism.delta.PropertyDelta) SearchResultMetadata(com.evolveum.midpoint.schema.SearchResultMetadata) QName(javax.xml.namespace.QName) NotNull(org.jetbrains.annotations.NotNull) Clock(com.evolveum.midpoint.common.Clock) Validate(org.apache.commons.lang.Validate) CreateCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.CreateCapabilityType) java.util(java.util) com.evolveum.midpoint.util(com.evolveum.midpoint.util) com.evolveum.midpoint.xml.ns._public.common.common_3(com.evolveum.midpoint.xml.ns._public.common.common_3) SchemaConstants(com.evolveum.midpoint.schema.constants.SchemaConstants) OperationResult(com.evolveum.midpoint.schema.result.OperationResult) Trace(com.evolveum.midpoint.util.logging.Trace) ItemDelta(com.evolveum.midpoint.prism.delta.ItemDelta) GenericConnectorException(com.evolveum.midpoint.provisioning.api.GenericConnectorException) RepositoryCache(com.evolveum.midpoint.repo.cache.RepositoryCache) JavaTypeConverter(com.evolveum.midpoint.prism.util.JavaTypeConverter) ObjectTypeUtil(com.evolveum.midpoint.schema.util.ObjectTypeUtil) SchemaDebugUtil(com.evolveum.midpoint.schema.util.SchemaDebugUtil) CapabilityUtil(com.evolveum.midpoint.schema.CapabilityUtil) AddRemoveAttributeValuesCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.AddRemoveAttributeValuesCapabilityType) ContainerDelta(com.evolveum.midpoint.prism.delta.ContainerDelta) PrismUtil(com.evolveum.midpoint.prism.util.PrismUtil) LiveSyncCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.LiveSyncCapabilityType) XMLGregorianCalendar(javax.xml.datatype.XMLGregorianCalendar) ItemPath(com.evolveum.midpoint.prism.path.ItemPath) QueryBuilder(com.evolveum.midpoint.prism.query.builder.QueryBuilder) MatchingRule(com.evolveum.midpoint.prism.match.MatchingRule) Component(org.springframework.stereotype.Component) com.evolveum.midpoint.provisioning.ucf.api(com.evolveum.midpoint.provisioning.ucf.api) com.evolveum.midpoint.schema.processor(com.evolveum.midpoint.schema.processor) AsynchronousOperationResult(com.evolveum.midpoint.schema.result.AsynchronousOperationResult) ActivationStatusCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationStatusCapabilityType) ProvisioningUtil(com.evolveum.midpoint.provisioning.util.ProvisioningUtil) ShadowUtil(com.evolveum.midpoint.schema.util.ShadowUtil) ObjectQuery(com.evolveum.midpoint.prism.query.ObjectQuery) ActivationLockoutStatusCapabilityType(com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationLockoutStatusCapabilityType) TraceManager(com.evolveum.midpoint.util.logging.TraceManager) SearchResultMetadata(com.evolveum.midpoint.schema.SearchResultMetadata) GenericConnectorException(com.evolveum.midpoint.provisioning.api.GenericConnectorException)

Example 10 with GenericConnectorException

use of com.evolveum.midpoint.provisioning.api.GenericConnectorException in project midpoint by Evolveum.

the class EntitlementConverter method collectEntitlementsAsObjectOperationDelete.

/////////
// DELETE
/////////
/**
	 * This is somehow different that all the other methods. We are not following the content of a shadow or delta. We are following
	 * the definitions. This is to avoid the need to read the object that is going to be deleted. In fact, the object should not be there
	 * any more, but we still want to clean up entitlement membership based on the information from the shadow.  
	 */
public <T> void collectEntitlementsAsObjectOperationDelete(ProvisioningContext subjectCtx, final Map<ResourceObjectDiscriminator, ResourceObjectOperations> roMap, PrismObject<ShadowType> subjectShadow, OperationResult parentResult) throws SchemaException, CommunicationException, ObjectNotFoundException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
    Collection<RefinedAssociationDefinition> entitlementAssociationDefs = subjectCtx.getObjectClassDefinition().getAssociationDefinitions();
    if (entitlementAssociationDefs == null || entitlementAssociationDefs.isEmpty()) {
        // Nothing to do
        LOGGER.trace("No associations in deleted shadow");
        return;
    }
    ResourceAttributeContainer subjectAttributesContainer = ShadowUtil.getAttributesContainer(subjectShadow);
    for (final RefinedAssociationDefinition assocDefType : subjectCtx.getObjectClassDefinition().getAssociationDefinitions()) {
        if (assocDefType.getResourceObjectAssociationType().getDirection() != ResourceObjectAssociationDirectionType.OBJECT_TO_SUBJECT) {
            // We can ignore these. They will die together with the object. No need to explicitly delete them.
            LOGGER.trace("Ignoring subject-to-object association in deleted shadow");
            continue;
        }
        if (!assocDefType.requiresExplicitReferentialIntegrity()) {
            // Referential integrity not required for this one
            LOGGER.trace("Ignoring association in deleted shadow because it does not require explicit referential integrity assurance");
            continue;
        }
        if (assocDefType.getAuxiliaryObjectClass() != null && !subjectCtx.getObjectClassDefinition().hasAuxiliaryObjectClass(assocDefType.getAuxiliaryObjectClass())) {
            LOGGER.trace("Ignoring association in deleted shadow because subject does not have {} auxiliary object class", assocDefType.getAuxiliaryObjectClass());
            continue;
        }
        QName associationName = assocDefType.getName();
        if (associationName == null) {
            throw new SchemaException("No name in entitlement association " + assocDefType + " in " + subjectCtx.getResource());
        }
        ShadowKindType entitlementKind = assocDefType.getKind();
        if (entitlementKind == null) {
            entitlementKind = ShadowKindType.ENTITLEMENT;
        }
        for (String entitlementIntent : assocDefType.getIntents()) {
            final ProvisioningContext entitlementCtx = subjectCtx.spawn(entitlementKind, entitlementIntent);
            final RefinedObjectClassDefinition entitlementOcDef = entitlementCtx.getObjectClassDefinition();
            if (entitlementOcDef == null) {
                throw new SchemaException("No definition for entitlement intent(s) '" + assocDefType.getIntents() + "' defined in entitlement association " + associationName + " in " + subjectCtx.getResource());
            }
            final QName assocAttrName = assocDefType.getResourceObjectAssociationType().getAssociationAttribute();
            if (assocAttrName == null) {
                throw new SchemaException("No association attribute defined in entitlement association '" + associationName + "' in " + subjectCtx.getResource());
            }
            final RefinedAttributeDefinition assocAttrDef = entitlementOcDef.findAttributeDefinition(assocAttrName);
            if (assocAttrDef == null) {
                throw new SchemaException("Association attribute '" + assocAttrName + "'defined in entitlement association '" + associationName + "' was not found in schema for " + subjectCtx.getResource());
            }
            QName valueAttrName = assocDefType.getResourceObjectAssociationType().getValueAttribute();
            if (valueAttrName == null) {
                throw new SchemaException("No value attribute defined in entitlement association '" + associationName + "' in " + subjectCtx.getResource());
            }
            final ResourceAttribute<T> valueAttr = subjectAttributesContainer.findAttribute(valueAttrName);
            if (valueAttr == null || valueAttr.isEmpty()) {
                // Although we cannot really remedy the situation now, we at least throw an error so the problem is detected.
                throw new SchemaException("Value attribute " + valueAttrName + " has no value; attribute defined in entitlement association '" + associationName + "' in " + subjectCtx.getResource());
            }
            if (valueAttr.size() > 1) {
                throw new SchemaException("Value attribute " + valueAttrName + " has no more than one value; attribute defined in entitlement association '" + associationName + "' in " + subjectCtx.getResource());
            }
            ObjectQuery query = createQuery(assocDefType, assocAttrDef, valueAttr);
            AttributesToReturn attributesToReturn = ProvisioningUtil.createAttributesToReturn(entitlementCtx);
            SearchHierarchyConstraints searchHierarchyConstraints = null;
            ResourceObjectReferenceType baseContextRef = entitlementOcDef.getBaseContext();
            if (baseContextRef != null) {
                PrismObject<ShadowType> baseContextShadow = resourceObjectReferenceResolver.resolve(subjectCtx, baseContextRef, null, "base context specification in " + entitlementOcDef, parentResult);
                RefinedObjectClassDefinition baseContextObjectClassDefinition = subjectCtx.getRefinedSchema().determineCompositeObjectClassDefinition(baseContextShadow);
                ResourceObjectIdentification baseContextIdentification = ShadowUtil.getResourceObjectIdentification(baseContextShadow, baseContextObjectClassDefinition);
                searchHierarchyConstraints = new SearchHierarchyConstraints(baseContextIdentification, null);
            }
            ResultHandler<ShadowType> handler = new ResultHandler<ShadowType>() {

                @Override
                public boolean handle(PrismObject<ShadowType> entitlementShadow) {
                    Collection<? extends ResourceAttribute<?>> primaryIdentifiers = ShadowUtil.getPrimaryIdentifiers(entitlementShadow);
                    ResourceObjectDiscriminator disc = new ResourceObjectDiscriminator(entitlementOcDef.getTypeName(), primaryIdentifiers);
                    ResourceObjectOperations operations = roMap.get(disc);
                    if (operations == null) {
                        operations = new ResourceObjectOperations();
                        roMap.put(disc, operations);
                        operations.setResourceObjectContext(entitlementCtx);
                        Collection<? extends ResourceAttribute<?>> allIdentifiers = ShadowUtil.getAllIdentifiers(entitlementShadow);
                        operations.setAllIdentifiers(allIdentifiers);
                    }
                    PropertyDelta<T> attributeDelta = null;
                    for (Operation operation : operations.getOperations()) {
                        if (operation instanceof PropertyModificationOperation) {
                            PropertyModificationOperation propOp = (PropertyModificationOperation) operation;
                            if (propOp.getPropertyDelta().getElementName().equals(assocAttrName)) {
                                attributeDelta = propOp.getPropertyDelta();
                            }
                        }
                    }
                    if (attributeDelta == null) {
                        attributeDelta = assocAttrDef.createEmptyDelta(new ItemPath(ShadowType.F_ATTRIBUTES, assocAttrName));
                        PropertyModificationOperation attributeModification = new PropertyModificationOperation(attributeDelta);
                        attributeModification.setMatchingRuleQName(assocDefType.getMatchingRule());
                        operations.add(attributeModification);
                    }
                    attributeDelta.addValuesToDelete(valueAttr.getClonedValues());
                    if (LOGGER.isTraceEnabled()) {
                        LOGGER.trace("Association in deleted shadow delta:\n{}", attributeDelta.debugDump());
                    }
                    return true;
                }
            };
            try {
                LOGGER.trace("Searching for associations in deleted shadow, query: {}", query);
                ConnectorInstance connector = subjectCtx.getConnector(ReadCapabilityType.class, parentResult);
                connector.search(entitlementOcDef, query, handler, attributesToReturn, null, searchHierarchyConstraints, subjectCtx, parentResult);
            } catch (TunnelException e) {
                throw (SchemaException) e.getCause();
            } catch (GenericFrameworkException e) {
                throw new GenericConnectorException(e.getMessage(), e);
            }
        }
    }
}
Also used : AttributesToReturn(com.evolveum.midpoint.provisioning.ucf.api.AttributesToReturn) ResourceAttributeContainer(com.evolveum.midpoint.schema.processor.ResourceAttributeContainer) ResultHandler(com.evolveum.midpoint.provisioning.ucf.api.ResultHandler) Operation(com.evolveum.midpoint.provisioning.ucf.api.Operation) PropertyModificationOperation(com.evolveum.midpoint.provisioning.ucf.api.PropertyModificationOperation) PrismObject(com.evolveum.midpoint.prism.PrismObject) TunnelException(com.evolveum.midpoint.util.exception.TunnelException) SearchHierarchyConstraints(com.evolveum.midpoint.schema.processor.SearchHierarchyConstraints) ResourceObjectIdentification(com.evolveum.midpoint.schema.processor.ResourceObjectIdentification) GenericConnectorException(com.evolveum.midpoint.provisioning.api.GenericConnectorException) PropertyModificationOperation(com.evolveum.midpoint.provisioning.ucf.api.PropertyModificationOperation) ResourceObjectReferenceType(com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectReferenceType) SchemaException(com.evolveum.midpoint.util.exception.SchemaException) GenericFrameworkException(com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException) QName(javax.xml.namespace.QName) ShadowType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType) ObjectQuery(com.evolveum.midpoint.prism.query.ObjectQuery) ConnectorInstance(com.evolveum.midpoint.provisioning.ucf.api.ConnectorInstance) ShadowKindType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType) ItemPath(com.evolveum.midpoint.prism.path.ItemPath)

Aggregations

GenericConnectorException (com.evolveum.midpoint.provisioning.api.GenericConnectorException)11 GenericFrameworkException (com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException)5 OperationResult (com.evolveum.midpoint.schema.result.OperationResult)5 ObjectQuery (com.evolveum.midpoint.prism.query.ObjectQuery)4 ConnectorInstance (com.evolveum.midpoint.provisioning.ucf.api.ConnectorInstance)4 AsynchronousOperationResult (com.evolveum.midpoint.schema.result.AsynchronousOperationResult)4 QName (javax.xml.namespace.QName)4 ItemPath (com.evolveum.midpoint.prism.path.ItemPath)3 ResourceObjectIdentification (com.evolveum.midpoint.schema.processor.ResourceObjectIdentification)3 SchemaException (com.evolveum.midpoint.util.exception.SchemaException)3 ResourceType (com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType)3 PrismObject (com.evolveum.midpoint.prism.PrismObject)2 ItemDelta (com.evolveum.midpoint.prism.delta.ItemDelta)2 PropertyDelta (com.evolveum.midpoint.prism.delta.PropertyDelta)2 AttributesToReturn (com.evolveum.midpoint.provisioning.ucf.api.AttributesToReturn)2 ResultHandler (com.evolveum.midpoint.provisioning.ucf.api.ResultHandler)2 ResourceAttributeContainer (com.evolveum.midpoint.schema.processor.ResourceAttributeContainer)2 SearchHierarchyConstraints (com.evolveum.midpoint.schema.processor.SearchHierarchyConstraints)2 CommunicationException (com.evolveum.midpoint.util.exception.CommunicationException)2 ConfigurationException (com.evolveum.midpoint.util.exception.ConfigurationException)2