Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/Evolveum/midpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
katkav committed Aug 25, 2017
2 parents 96017be + b499aa8 commit 029d373
Show file tree
Hide file tree
Showing 21 changed files with 1,199 additions and 115 deletions.
Expand Up @@ -461,6 +461,11 @@ public Collection<? extends QName> getNamesOfAssociationsWithOutboundExpressions
.map(a -> a.getName())
.collect(Collectors.toCollection(HashSet::new));
}

@Override
public boolean isTolerantAuxiliaryObjectClasses() {
return structuralObjectClassDefinition.isTolerantAuxiliaryObjectClasses();
}

@Override
public boolean hasAuxiliaryObjectClass(QName expectedObjectClassName) {
Expand Down
Expand Up @@ -591,6 +591,11 @@ public boolean hasAuxiliaryObjectClass(QName expectedObjectClassName) {
return refinedObjectClassDefinition.hasAuxiliaryObjectClass(expectedObjectClassName);
}

@Override
public boolean isTolerantAuxiliaryObjectClasses() {
return refinedObjectClassDefinition.isTolerantAuxiliaryObjectClasses();
}

@Override
public ObjectQuery createShadowSearchQuery(String resourceOid) throws SchemaException {
return refinedObjectClassDefinition.createShadowSearchQuery(resourceOid);
Expand Down
Expand Up @@ -147,6 +147,8 @@ default PrismObject<ShadowType> createBlankShadow() {
Collection<RefinedObjectClassDefinition> getAuxiliaryObjectClassDefinitions();

boolean hasAuxiliaryObjectClass(QName expectedObjectClassName);

boolean isTolerantAuxiliaryObjectClasses();

Collection<ResourceObjectPattern> getProtectedObjectPatterns();

Expand Down
Expand Up @@ -409,6 +409,19 @@ public boolean hasAuxiliaryObjectClass(QName expectedObjectClassName) {
return auxiliaryObjectClassDefinitions.stream()
.anyMatch(def -> QNameUtil.match(def.getTypeName(), expectedObjectClassName));
}

@Override
public boolean isTolerantAuxiliaryObjectClasses() {
if (schemaHandlingObjectTypeDefinitionType == null) {
return false;
}
Boolean tolerantAuxiliaryObjectClasses = schemaHandlingObjectTypeDefinitionType.isTolerantAuxiliaryObjectClasses();
if (tolerantAuxiliaryObjectClasses == null) {
return false;
} else {
return tolerantAuxiliaryObjectClasses;
}
}

@Override
public Collection<ResourceObjectPattern> getProtectedObjectPatterns() {
Expand Down
Expand Up @@ -4360,6 +4360,17 @@
point to object class definition (complex type definition in resource schema) and
this definition should be marked as auxiliary.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="tolerantAuxiliaryObjectClasses" type="xsd:boolean" minOccurs="0" maxOccurs="1" default="false">
<xsd:annotation>
<xsd:documentation>
If set to true then midPoitn will tolerate existing auxiliary object classes on resource
objects. MidPoitn will add/remove auxiliary object classes only if there is an explicit
operation for that (e.g. assign/unassign of role with auxiliary object class definition).
If set to false then midPoint will strictly synchronize auxiliary object classes of resource
objects with the definition given in midPoint configuration.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="baseContext" type="tns:ResourceObjectReferenceType" minOccurs="0">
Expand Down
Expand Up @@ -539,6 +539,8 @@ private LinkedHashSet<String> getSearchAttributes() {
LinkedHashSet<String> attrs = new LinkedHashSet<String>();
attrs.add("*");
attrs.add("ds-pwp-account-disabled");
attrs.add("createTimestamp");
attrs.add("modifyTimestamp");
return attrs;
}

Expand Down
Expand Up @@ -238,12 +238,14 @@ private void reconcileAuxiliaryObjectClasses(LensProjectionContext projCtx) thro
shouldBePvwo.getSource(), "it is given");
}
}

for (PrismPropertyValue<QName> isPValue : arePValues) {
if (!isInPvwoValues(valueMatcher, isPValue.getValue(), shouldBePValues)) {
auxObjectClassChanged = true;
recordDelta(valueMatcher, projCtx, ItemPath.EMPTY_PATH, propDef, ModificationType.DELETE,
isPValue.getValue(), null, "it is not given");

if (!projCtx.getStructuralObjectClassDefinition().isTolerantAuxiliaryObjectClasses()) {
for (PrismPropertyValue<QName> isPValue : arePValues) {
if (!isInPvwoValues(valueMatcher, isPValue.getValue(), shouldBePValues)) {
auxObjectClassChanged = true;
recordDelta(valueMatcher, projCtx, ItemPath.EMPTY_PATH, propDef, ModificationType.DELETE,
isPValue.getValue(), null, "it is not given");
}
}
}

Expand Down
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2010-2017 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.evolveum.midpoint.repo.api;

import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;

/**
* @author mederly
*/
@FunctionalInterface
public interface ModificationPrecondition<T extends ObjectType> {

/**
* Problem can be reported either by returning false or by throwing PreconditionViolationException directly.
* The former method is easier while the latter one gives a possibility to provide a custom exception message.
*/
boolean holds(PrismObject<T> object) throws PreconditionViolationException;
}
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2010-2017 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.evolveum.midpoint.repo.api;

/**
* @author mederly
*/
public class PreconditionViolationException extends Exception {

public PreconditionViolationException(String message) {
super(message);
}

public PreconditionViolationException(String message, Throwable cause) {
super(message, cause);
}
}
Expand Up @@ -24,9 +24,7 @@
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.schema.*;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -367,6 +365,9 @@ <T extends ObjectType> int countObjects(Class<T> type, ObjectQuery query,
*
* TODO: optimistic locking
*
* Note: the precondition is checked only if actual modification is going to take place
* (not e.g. if the list of modifications is empty).
*
* @param parentResult
* parent OperationResult (in/out)
*
Expand All @@ -385,6 +386,10 @@ <T extends ObjectType> void modifyObject(Class<T> type, String oid, Collection<?
<T extends ObjectType> void modifyObject(Class<T> type, String oid, Collection<? extends ItemDelta> modifications, RepoModifyOptions options, OperationResult parentResult)
throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException;

<T extends ObjectType> void modifyObject(Class<T> type, String oid, Collection<? extends ItemDelta> modifications,
ModificationPrecondition<T> precondition, RepoModifyOptions options, OperationResult parentResult)
throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, PreconditionViolationException;

/**
* <p>Deletes object with specified OID.</p>
* <p>
Expand Down
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2010-2017 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.evolveum.midpoint.repo.api;

import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import org.jetbrains.annotations.NotNull;

import java.io.Serializable;

/**
* @author mederly
*/
public class VersionPrecondition<T extends ObjectType> implements ModificationPrecondition<T>, Serializable {

@NotNull private final String expectedVersion;

public VersionPrecondition(String expectedVersion) {
this.expectedVersion = normalize(expectedVersion);
}

public VersionPrecondition(@NotNull PrismObject<T> object) {
this.expectedVersion = normalize(object.getVersion());
}

@Override
public boolean holds(PrismObject<T> object) throws PreconditionViolationException {
String realVersion = normalize(object.getVersion());
if (!expectedVersion.equals(realVersion)) {
throw new PreconditionViolationException("Real version of the object (" + object.getVersion()
+ ") does not match expected one (" + expectedVersion + ") for " + object);
}
return true;
}

private String normalize(String version) {
// this is a bit questionable - actually, null version should not occur here
return version != null ? version : "0";
}
}
Expand Up @@ -20,10 +20,7 @@
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.repo.api.RepoAddOptions;
import com.evolveum.midpoint.repo.api.RepoModifyOptions;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.repo.api.ConflictWatcher;
import com.evolveum.midpoint.repo.api.*;
import com.evolveum.midpoint.schema.*;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException;
Expand Down Expand Up @@ -249,7 +246,18 @@ public <T extends ObjectType> void modifyObject(Class<T> type, String oid, Colle
public <T extends ObjectType> void modifyObject(Class<T> type, String oid, Collection<? extends ItemDelta> modifications,
RepoModifyOptions options, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException {
try {
repository.modifyObject(type, oid, modifications, options, parentResult);
modifyObject(type, oid, modifications, null, options, parentResult);
} catch (PreconditionViolationException e) {
throw new AssertionError(e);
}
}

@Override
public <T extends ObjectType> void modifyObject(Class<T> type, String oid, Collection<? extends ItemDelta> modifications,
ModificationPrecondition<T> precondition, RepoModifyOptions options, OperationResult parentResult)
throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException, PreconditionViolationException {
try {
repository.modifyObject(type, oid, modifications, precondition, options, parentResult);
} finally {
// this changes the object. We are too lazy to apply changes ourselves, so just invalidate
// the object in cache
Expand Down

0 comments on commit 029d373

Please sign in to comment.