use of com.evolveum.midpoint.prism.PrismObject in project midpoint by Evolveum.
the class AssignmentProcessor method setReferences.
private <F extends ObjectType> void setReferences(LensFocusContext<F> focusContext, QName itemName, Collection<PrismReferenceValue> targetState) throws SchemaException {
PrismObject<F> focusOld = focusContext.getObjectOld();
if (focusOld == null) {
if (targetState.isEmpty()) {
return;
}
} else {
PrismReference existingState = focusOld.findReference(itemName);
if (existingState == null || existingState.isEmpty()) {
if (targetState.isEmpty()) {
return;
}
} else {
// we don't use QNameUtil.match here, because we want to ensure we store qualified values there
// (and newValues are all qualified)
Comparator<PrismReferenceValue> comparator = (a, b) -> 2 * a.getOid().compareTo(b.getOid()) + (Objects.equals(a.getRelation(), b.getRelation()) ? 0 : 1);
if (MiscUtil.unorderedCollectionCompare(targetState, existingState.getValues(), comparator)) {
return;
}
}
}
PrismReferenceDefinition itemDef = focusContext.getObjectDefinition().findItemDefinition(itemName, PrismReferenceDefinition.class);
ReferenceDelta itemDelta = new ReferenceDelta(itemName, itemDef, focusContext.getObjectDefinition().getPrismContext());
itemDelta.setValuesToReplace(targetState);
focusContext.swallowToSecondaryDelta(itemDelta);
}
use of com.evolveum.midpoint.prism.PrismObject in project midpoint by Evolveum.
the class ContextLoader method loadFullShadow.
public <F extends ObjectType> void loadFullShadow(LensContext<F> context, LensProjectionContext projCtx, String reason, Task task, OperationResult result) throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
if (projCtx.isFullShadow()) {
// already loaded
return;
}
if (projCtx.isAdd() && projCtx.getOid() == null) {
// nothing to load yet
return;
}
if (projCtx.isThombstone()) {
// loading is futile
return;
}
ResourceShadowDiscriminator discr = projCtx.getResourceShadowDiscriminator();
if (discr != null && discr.getOrder() > 0) {
// It may be just too early to load the projection
if (LensUtil.hasLowerOrderContext(context, projCtx) && (context.getExecutionWave() < projCtx.getWave())) {
// We cannot reliably load the context now
return;
}
}
GetOperationOptions getOptions = GetOperationOptions.createAllowNotFound();
getOptions.setPointInTimeType(PointInTimeType.FUTURE);
if (SchemaConstants.CHANGE_CHANNEL_DISCOVERY_URI.equals(context.getChannel())) {
LOGGER.trace("Loading full resource object {} from provisioning - with doNotDiscover to avoid loops; reason: {}", projCtx, reason);
// Avoid discovery loops
getOptions.setDoNotDiscovery(true);
} else {
LOGGER.trace("Loading full resource object {} from provisioning (discovery enabled), reason: {}, channel: {}", projCtx, reason, context.getChannel());
}
try {
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(getOptions);
applyAttributesToGet(projCtx, options);
PrismObject<ShadowType> objectCurrent = provisioningService.getObject(ShadowType.class, projCtx.getOid(), options, task, result);
Validate.notNull(objectCurrent.getOid());
// TODO: use setLoadedObject() instead?
projCtx.setObjectCurrent(objectCurrent);
ShadowType oldShadow = objectCurrent.asObjectable();
projCtx.determineFullShadowFlag(oldShadow.getFetchResult());
// The getObject may return different OID than we have requested in case that compensation happened
// TODO: this probably need to be fixed in the consistency mechanism
// TODO: the following line is a temporary fix
projCtx.setOid(objectCurrent.getOid());
} catch (ObjectNotFoundException ex) {
LOGGER.trace("Load of full resource object {} ended with ObjectNotFoundException (options={})", projCtx, getOptions);
if (projCtx.isDelete()) {
//this is OK, shadow was deleted, but we will continue in processing with old shadow..and set it as full so prevent from other full loading
projCtx.setFullShadow(true);
} else {
boolean compensated = false;
if (!GetOperationOptions.isDoNotDiscovery(getOptions)) {
// The account might have been re-created by the discovery.
// Reload focus, try to find out if there is a new matching link (and the old is gone)
LensFocusContext<F> focusContext = context.getFocusContext();
if (focusContext != null) {
Class<F> focusClass = focusContext.getObjectTypeClass();
if (FocusType.class.isAssignableFrom(focusClass)) {
LOGGER.trace("Reloading focus to check for new links");
PrismObject<F> focusCurrent = cacheRepositoryService.getObject(focusContext.getObjectTypeClass(), focusContext.getOid(), null, result);
FocusType focusType = (FocusType) focusCurrent.asObjectable();
for (ObjectReferenceType linkRef : focusType.getLinkRef()) {
if (linkRef.getOid().equals(projCtx.getOid())) {
// The deleted shadow is still in the linkRef. This should not happen, but it obviously happens sometimes.
// Maybe some strange race condition? Anyway, we want a robust behavior and this linkeRef should NOT be there.
// So simple remove it.
LOGGER.warn("The OID " + projCtx.getOid() + " of deleted shadow still exists in the linkRef after discovery (" + focusCurrent + "), removing it");
ReferenceDelta unlinkDelta = ReferenceDelta.createModificationDelete(FocusType.F_LINK_REF, focusContext.getObjectDefinition(), linkRef.asReferenceValue().clone());
focusContext.swallowToSecondaryDelta(unlinkDelta);
continue;
}
boolean found = false;
for (LensProjectionContext pCtx : context.getProjectionContexts()) {
if (linkRef.getOid().equals(pCtx.getOid())) {
found = true;
break;
}
}
if (!found) {
// This link is new, it is not in the existing lens context
PrismObject<ShadowType> newLinkRepoShadow = cacheRepositoryService.getObject(ShadowType.class, linkRef.getOid(), null, result);
if (ShadowUtil.matches(newLinkRepoShadow, projCtx.getResourceShadowDiscriminator())) {
LOGGER.trace("Found new matching link: {}, updating projection context", newLinkRepoShadow);
// MID-3317
LOGGER.trace("Applying definition from provisioning first.");
provisioningService.applyDefinition(newLinkRepoShadow, task, result);
projCtx.setObjectCurrent(newLinkRepoShadow);
projCtx.setOid(newLinkRepoShadow.getOid());
projCtx.recompute();
compensated = true;
break;
} else {
LOGGER.trace("Found new link: {}, but skipping it because it does not match the projection context", newLinkRepoShadow);
}
}
}
}
}
}
if (!compensated) {
LOGGER.trace("ObjectNotFound error is not compensated, setting context to thombstone");
projCtx.getResourceShadowDiscriminator().setThombstone(true);
projCtx.setExists(false);
projCtx.setFullShadow(false);
}
}
}
projCtx.recompute();
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Loaded full resource object:\n{}", projCtx.debugDump(1));
}
}
use of com.evolveum.midpoint.prism.PrismObject in project midpoint by Evolveum.
the class ContextLoader method getOrCreateAccountContext.
private <F extends FocusType> LensProjectionContext getOrCreateAccountContext(LensContext<F> context, PrismObject<ShadowType> projection, Task task, OperationResult result) throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, PolicyViolationException, ExpressionEvaluationException {
ShadowType accountType = projection.asObjectable();
String resourceOid = ShadowUtil.getResourceOid(accountType);
if (resourceOid == null) {
throw new SchemaException("The " + projection + " has null resource reference OID");
}
LensProjectionContext projectionContext = context.findProjectionContextByOid(accountType.getOid());
if (projectionContext == null) {
String intent = ShadowUtil.getIntent(accountType);
ShadowKindType kind = ShadowUtil.getKind(accountType);
ResourceType resource = LensUtil.getResourceReadOnly(context, resourceOid, provisioningService, task, result);
intent = LensUtil.refineProjectionIntent(kind, intent, resource, prismContext);
boolean thombstone = false;
if (ShadowUtil.isDead(accountType)) {
thombstone = true;
}
ResourceShadowDiscriminator rsd = new ResourceShadowDiscriminator(resourceOid, kind, intent, thombstone);
projectionContext = LensUtil.getOrCreateProjectionContext(context, rsd);
if (projectionContext.getOid() == null) {
projectionContext.setOid(projection.getOid());
} else if (projection.getOid() != null && !projectionContext.getOid().equals(projection.getOid())) {
// slightly inefficient here and check for existing shadow existence
try {
GetOperationOptions rootOpt = GetOperationOptions.createPointInTimeType(PointInTimeType.FUTURE);
rootOpt.setDoNotDiscovery(true);
Collection<SelectorOptions<GetOperationOptions>> opts = SelectorOptions.createCollection(rootOpt);
LOGGER.trace("Projection conflict detected, exsting: {}, new {}", projectionContext.getOid(), projection.getOid());
PrismObject<ShadowType> existingShadow = provisioningService.getObject(ShadowType.class, projectionContext.getOid(), opts, task, result);
// Maybe it is the other way around
try {
PrismObject<ShadowType> newShadow = provisioningService.getObject(ShadowType.class, projection.getOid(), opts, task, result);
// Obviously, two projections with the same discriminator exists
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Projection {} already exists in context\nExisting:\n{}\nNew:\n{}", new Object[] { rsd, existingShadow.debugDump(1), newShadow.debugDump(1) });
}
throw new PolicyViolationException("Projection " + rsd + " already exists in context (existing " + existingShadow + ", new " + projection);
} catch (ObjectNotFoundException e) {
// This is somehow expected, fix it and we can go on
result.muteLastSubresultError();
// We have to create new context in this case, but it has to have thumbstone set
rsd.setThombstone(true);
projectionContext = LensUtil.getOrCreateProjectionContext(context, rsd);
// We have to mark it as dead right now, otherwise the uniqueness check may fail
markShadowDead(projection.getOid(), result);
}
} catch (ObjectNotFoundException e) {
// This is somehow expected, fix it and we can go on
result.muteLastSubresultError();
String shadowOid = projectionContext.getOid();
projectionContext.getResourceShadowDiscriminator().setThombstone(true);
projectionContext = LensUtil.getOrCreateProjectionContext(context, rsd);
// We have to mark it as dead right now, otherwise the uniqueness check may fail
markShadowDead(shadowOid, result);
}
}
}
return projectionContext;
}
use of com.evolveum.midpoint.prism.PrismObject in project midpoint by Evolveum.
the class FocusConstraintsChecker method checkPropertyUniqueness.
private <T> boolean checkPropertyUniqueness(PrismObject<F> objectNew, ItemPath propPath, LensContext<F> context, OperationResult result) throws SchemaException {
PrismProperty<T> property = objectNew.findProperty(propPath);
if (property == null || property.isEmpty()) {
throw new SchemaException("No property " + propPath + " in new object " + objectNew + ", cannot check uniqueness");
}
String oid = objectNew.getOid();
ObjectQuery query = QueryBuilder.queryFor(objectNew.getCompileTimeClass(), prismContext).itemAs(property).build();
List<PrismObject<F>> foundObjects = repositoryService.searchObjects(objectNew.getCompileTimeClass(), query, null, result);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Uniqueness check of {}, property {} resulted in {} results, using query:\n{}", new Object[] { objectNew, propPath, foundObjects.size(), query.debugDump() });
}
if (foundObjects.isEmpty()) {
return true;
}
if (foundObjects.size() > 1) {
LOGGER.trace("Found more than one object with property " + propPath + " = " + property);
message("Found more than one object with property " + propPath + " = " + property);
return false;
}
LOGGER.trace("Comparing {} and {}", foundObjects.get(0).getOid(), oid);
boolean match = foundObjects.get(0).getOid().equals(oid);
if (!match) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Found conflicting existing object with property " + propPath + " = " + property + ":\n" + foundObjects.get(0).debugDump());
}
message("Found conflicting existing object with property " + propPath + " = " + property + ": " + foundObjects.get(0));
conflictingObject = foundObjects.get(0);
}
return match;
}
use of com.evolveum.midpoint.prism.PrismObject in project midpoint by Evolveum.
the class TestUcfDummyMulti method test210TwoBlockingSearches.
@Test
public void test210TwoBlockingSearches() throws Exception {
final String TEST_NAME = "test210TwoBlockingSearches";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
final ObjectClassComplexTypeDefinition accountDefinition = resourceSchema.findDefaultObjectClassDefinition(ShadowKindType.ACCOUNT);
// Determine object class from the schema
final OperationResult result1 = new OperationResult(this.getClass().getName() + "." + TEST_NAME);
final List<PrismObject<ShadowType>> searchResults1 = new ArrayList<PrismObject<ShadowType>>();
final ResultHandler<ShadowType> handler1 = new ResultHandler<ShadowType>() {
@Override
public boolean handle(PrismObject<ShadowType> shadow) {
checkUcfShadow(shadow, accountDefinition);
searchResults1.add(shadow);
return true;
}
};
final OperationResult result2 = new OperationResult(this.getClass().getName() + "." + TEST_NAME);
final List<PrismObject<ShadowType>> searchResults2 = new ArrayList<PrismObject<ShadowType>>();
final ResultHandler<ShadowType> handler2 = new ResultHandler<ShadowType>() {
@Override
public boolean handle(PrismObject<ShadowType> shadow) {
checkUcfShadow(shadow, accountDefinition);
searchResults2.add(shadow);
return true;
}
};
dummyResource.setBlockOperations(true);
// WHEN
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
cc.search(accountDefinition, new ObjectQuery(), handler1, null, null, null, null, result1);
} catch (CommunicationException | GenericFrameworkException | SchemaException | SecurityViolationException | ObjectNotFoundException e) {
LOGGER.error("Error in the search: {}", e.getMessage(), e);
}
}
});
t1.setName("search1");
t1.start();
// Give the new thread a chance to get blocked
Thread.sleep(500);
ConnectorOperationalStatus opStat = cc.getOperationalStatus();
display("stats (blocked 1)", opStat);
assertEquals("Wrong pool active", (Integer) 1, opStat.getPoolStatusNumActive());
assertEquals("Wrong pool active", (Integer) 0, opStat.getPoolStatusNumIdle());
assertEquals("Unexpected number of search results", 0, searchResults1.size());
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
cc.search(accountDefinition, new ObjectQuery(), handler2, null, null, null, null, result2);
} catch (CommunicationException | GenericFrameworkException | SchemaException | SecurityViolationException | ObjectNotFoundException e) {
LOGGER.error("Error in the search: {}", e.getMessage(), e);
}
}
});
t2.setName("search2");
t2.start();
// Give the new thread a chance to get blocked
Thread.sleep(500);
opStat = cc.getOperationalStatus();
display("stats (blocked 2)", opStat);
assertEquals("Wrong pool active", (Integer) 2, opStat.getPoolStatusNumActive());
assertEquals("Wrong pool active", (Integer) 0, opStat.getPoolStatusNumIdle());
assertEquals("Unexpected number of search results", 0, searchResults1.size());
dummyResource.unblockAll();
t1.join();
t2.join();
dummyResource.setBlockOperations(false);
// THEN
assertEquals("Unexpected number of search results 1", 1, searchResults1.size());
assertEquals("Unexpected number of search results 2", 1, searchResults2.size());
opStat = cc.getOperationalStatus();
display("stats (final)", opStat);
assertEquals("Wrong pool active", (Integer) 0, opStat.getPoolStatusNumActive());
assertEquals("Wrong pool active", (Integer) 2, opStat.getPoolStatusNumIdle());
PrismObject<ShadowType> searchResult1 = searchResults1.get(0);
display("Search result 1", searchResult1);
PrismObject<ShadowType> searchResult2 = searchResults2.get(0);
display("Search result 2", searchResult2);
}
Aggregations