use of com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectReferenceType in project midpoint by Evolveum.
the class ResourceObjectReferenceResolver method resolve.
PrismObject<ShadowType> resolve(ProvisioningContext ctx, ResourceObjectReferenceType resourceObjectReference, QName objectClass, final String desc, OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
if (resourceObjectReference == null) {
return null;
}
ObjectReferenceType shadowRef = resourceObjectReference.getShadowRef();
if (shadowRef != null && shadowRef.getOid() != null) {
if (resourceObjectReference.getResolutionFrequency() == null || resourceObjectReference.getResolutionFrequency() == ResourceObjectReferenceResolutionFrequencyType.ONCE) {
PrismObject<ShadowType> shadow = repositoryService.getObject(ShadowType.class, shadowRef.getOid(), null, result);
return shadow;
}
} else if (resourceObjectReference.getResolutionFrequency() == ResourceObjectReferenceResolutionFrequencyType.NEVER) {
throw new ObjectNotFoundException("No shadowRef OID in " + desc + " and resolution frequency set to NEVER");
}
if (resourceObjectReference.getObjectClass() != null) {
objectClass = resourceObjectReference.getObjectClass();
if (objectClass.getNamespaceURI() == null) {
objectClass = new QName(ResourceTypeUtil.getResourceNamespace(ctx.getResource()), objectClass.getLocalPart());
}
}
ProvisioningContext subctx = ctx.spawn(objectClass);
// Use "raw" definitions from the original schema to avoid endless loops
subctx.setUseRefinedDefinition(false);
subctx.assertDefinition();
ObjectQuery refQuery = QueryJaxbConvertor.createObjectQuery(ShadowType.class, resourceObjectReference.getFilter(), prismContext);
ObjectFilter baseFilter = ObjectQueryUtil.createResourceAndObjectClassFilter(ctx.getResource().getOid(), objectClass, prismContext);
ObjectFilter filter = AndFilter.createAnd(baseFilter, refQuery.getFilter());
ObjectQuery query = ObjectQuery.createObjectQuery(filter);
// TODO: implement "repo" search strategies
Collection<SelectorOptions<GetOperationOptions>> options = null;
final Holder<ShadowType> shadowHolder = new Holder<>();
ShadowHandler<ShadowType> handler = new ShadowHandler<ShadowType>() {
@Override
public boolean handle(ShadowType shadow) {
if (shadowHolder.getValue() != null) {
throw new IllegalStateException("More than one search results for " + desc);
}
shadowHolder.setValue(shadow);
return true;
}
};
shadowCache.searchObjectsIterative(subctx, query, options, handler, true, result);
// TODO: implement storage of OID (ONCE search frequency)
ShadowType shadowType = shadowHolder.getValue();
return shadowType == null ? null : shadowType.asPrismObject();
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectReferenceType in project midpoint by Evolveum.
the class EntitlementConverter method postProcessEntitlementEntitlementToSubject.
private <S extends ShadowType, T> void postProcessEntitlementEntitlementToSubject(ProvisioningContext subjectCtx, final PrismObject<S> resourceObject, RefinedAssociationDefinition assocDefType, final ProvisioningContext entitlementCtx, ResourceAttributeContainer attributesContainer, final PrismContainer<ShadowAssociationType> associationContainer, OperationResult parentResult) throws SchemaException, CommunicationException, ObjectNotFoundException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
ResourceType resourceType = subjectCtx.getResource();
final QName associationName = assocDefType.getName();
final RefinedObjectClassDefinition entitlementDef = entitlementCtx.getObjectClassDefinition();
if (associationName == null) {
throw new SchemaException("No name in entitlement association " + assocDefType + " in " + resourceType);
}
QName associationAuxiliaryObjectClass = assocDefType.getAuxiliaryObjectClass();
if (associationAuxiliaryObjectClass != null && associationAuxiliaryObjectClass.getNamespaceURI() != null && !associationAuxiliaryObjectClass.getNamespaceURI().equals(ResourceTypeUtil.getResourceNamespace(resourceType))) {
LOGGER.warn("Auxiliary object class {} in association {} does not have namespace that matches {}", associationAuxiliaryObjectClass, assocDefType.getName(), resourceType);
}
if (associationAuxiliaryObjectClass != null && !subjectCtx.getObjectClassDefinition().hasAuxiliaryObjectClass(associationAuxiliaryObjectClass)) {
LOGGER.trace("Ignoring association {} because subject does not have auxiliary object class {}, it has {}", associationName, associationAuxiliaryObjectClass, subjectCtx.getObjectClassDefinition().getAuxiliaryObjectClassDefinitions());
return;
}
QName assocAttrName = assocDefType.getResourceObjectAssociationType().getAssociationAttribute();
if (assocAttrName == null) {
throw new SchemaException("No association attribute defined in entitlement association '" + associationName + "' in " + resourceType);
}
RefinedAttributeDefinition assocAttrDef = entitlementDef.findAttributeDefinition(assocAttrName);
if (assocAttrDef == null) {
throw new SchemaException("Association attribute '" + assocAttrName + "'defined in entitlement association '" + associationName + "' was not found in schema for " + resourceType);
}
QName valueAttrName = assocDefType.getResourceObjectAssociationType().getValueAttribute();
if (valueAttrName == null) {
throw new SchemaException("No value attribute defined in entitlement association '" + associationName + "' in " + resourceType);
}
ResourceAttribute<T> valueAttr = attributesContainer.findAttribute(valueAttrName);
if (valueAttr == null || valueAttr.isEmpty()) {
LOGGER.trace("Ignoring association {} because subject does not have any value in attribute {}", associationName, valueAttrName);
return;
}
if (valueAttr.size() > 1) {
throw new SchemaException("Value attribute " + valueAttrName + " has no more than one value; attribute defined in entitlement association '" + associationName + "' in " + resourceType);
}
ObjectQuery query = createQuery(assocDefType, assocAttrDef, valueAttr);
AttributesToReturn attributesToReturn = ProvisioningUtil.createAttributesToReturn(entitlementCtx);
SearchHierarchyConstraints searchHierarchyConstraints = null;
ResourceObjectReferenceType baseContextRef = entitlementDef.getBaseContext();
if (baseContextRef != null) {
// TODO: this should be done once per search. Not in every run of postProcessEntitlementEntitlementToSubject
// this has to go outside of this method
PrismObject<ShadowType> baseContextShadow = resourceObjectReferenceResolver.resolve(subjectCtx, baseContextRef, null, "base context specification in " + entitlementDef, 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) {
PrismContainerValue<ShadowAssociationType> associationCVal = associationContainer.createNewValue();
associationCVal.asContainerable().setName(associationName);
Collection<ResourceAttribute<?>> entitlementIdentifiers = ShadowUtil.getAllIdentifiers(entitlementShadow);
try {
ResourceAttributeContainer identifiersContainer = new ResourceAttributeContainer(ShadowAssociationType.F_IDENTIFIERS, entitlementDef.toResourceAttributeContainerDefinition(), prismContext);
associationCVal.add(identifiersContainer);
identifiersContainer.getValue().addAll(ResourceAttribute.cloneCollection(entitlementIdentifiers));
// Remember the full shadow in user data. This is used later as an optimization to create the shadow in repo
identifiersContainer.setUserData(ResourceObjectConverter.FULL_SHADOW_KEY, entitlementShadow);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Processed entitlement-to-subject association for account {} and entitlement {}", ShadowUtil.getHumanReadableName(resourceObject), ShadowUtil.getHumanReadableName(entitlementShadow));
}
} catch (SchemaException e) {
throw new TunnelException(e);
}
return true;
}
};
ConnectorInstance connector = subjectCtx.getConnector(ReadCapabilityType.class, parentResult);
try {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Processed entitlement-to-subject association for account {}: query {}", ShadowUtil.getHumanReadableName(resourceObject), query);
}
try {
connector.search(entitlementDef, query, handler, attributesToReturn, null, searchHierarchyConstraints, subjectCtx, parentResult);
} catch (GenericFrameworkException e) {
throw new GenericConnectorException("Generic error in the connector " + connector + ". Reason: " + e.getMessage(), e);
}
} catch (TunnelException e) {
throw (SchemaException) e.getCause();
}
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectReferenceType in project midpoint by Evolveum.
the class ResourceObjectReferenceResolver method resolve.
/**
* Resolves a {@link ResourceObjectReferenceType}.
*
* @param useRawDefinition If true, object class definition is used (instead of object type definition).
* This is to avoid endless recursion when resolving the base context for object type.
*/
@Nullable
PrismObject<ShadowType> resolve(@NotNull ProvisioningContext ctx, @NotNull ResourceObjectReferenceType resourceObjectReference, boolean useRawDefinition, @NotNull String desc, @NotNull OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
ObjectReferenceType shadowRef = resourceObjectReference.getShadowRef();
if (shadowRef != null && shadowRef.getOid() != null) {
if (resourceObjectReference.getResolutionFrequency() == null || resourceObjectReference.getResolutionFrequency() == ResourceObjectReferenceResolutionFrequencyType.ONCE) {
PrismObject<ShadowType> shadow = repositoryService.getObject(ShadowType.class, shadowRef.getOid(), null, result);
shadowsFacade.applyDefinition(shadow, ctx.getTask(), result);
return shadow;
}
} else if (resourceObjectReference.getResolutionFrequency() == ResourceObjectReferenceResolutionFrequencyType.NEVER) {
throw new ObjectNotFoundException("No shadowRef OID in " + desc + " and resolution frequency set to NEVER");
}
argCheck(resourceObjectReference.getObjectClass() != null, "No object class name in object reference in %s", desc);
QName objectClassName = QNameUtil.qualifyIfNeeded(resourceObjectReference.getObjectClass(), MidPointConstants.NS_RI);
ProvisioningContext subCtx = useRawDefinition ? ctx.spawnForObjectClassWithRawDefinition(objectClassName) : ctx.spawnForObjectClass(objectClassName);
subCtx.assertDefinition();
ObjectQuery refQuery = prismContext.getQueryConverter().createObjectQuery(ShadowType.class, resourceObjectReference.getFilter());
// No variables. At least not now. We expect that mostly constants will be used here.
VariablesMap variables = new VariablesMap();
ObjectQuery evaluatedRefQuery = ExpressionUtil.evaluateQueryExpressions(refQuery, variables, MiscSchemaUtil.getExpressionProfile(), expressionFactory, prismContext, desc, ctx.getTask(), result);
ObjectFilter baseFilter = ObjectQueryUtil.createResourceAndObjectClassFilter(ctx.getResource().getOid(), objectClassName, prismContext);
ObjectFilter filter = prismContext.queryFactory().createAnd(baseFilter, evaluatedRefQuery.getFilter());
ObjectQuery query = prismContext.queryFactory().createQuery(filter);
// TODO: implement "repo" search strategies, don't forget to apply definitions
Holder<PrismObject<ShadowType>> shadowHolder = new Holder<>();
ResultHandler<ShadowType> handler = (shadow, objResult) -> {
if (shadowHolder.getValue() != null) {
throw new IllegalStateException("More than one search results for " + desc);
}
shadowHolder.setValue(shadow);
return true;
};
shadowsFacade.searchObjectsIterative(subCtx, query, null, handler, result);
return shadowHolder.getValue();
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectReferenceType 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;
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectReferenceType 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);
}
}
}
}
Aggregations