From 64f4e21ff801d6aa207424dfddbd801899917138 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 2 Nov 2016 10:45:32 +0100 Subject: [PATCH 1/2] Removed (too strict) check on 'any' definitions when applying them. This check was practically void before prism cleanup was carried out, as no definitions was of declared type xsd:any. --- .../midpoint/prism/PrismContainerDefinition.java | 2 -- .../prism/PrismContainerDefinitionImpl.java | 15 --------------- .../midpoint/prism/PrismContainerValue.java | 5 +---- 3 files changed, 1 insertion(+), 21 deletions(-) diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerDefinition.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerDefinition.java index 06cffa870b5..03498189513 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerDefinition.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerDefinition.java @@ -33,8 +33,6 @@ public interface PrismContainerDefinition extends ItemD ComplexTypeDefinition getComplexTypeDefinition(); - boolean isWildcard(); - @Override void revive(PrismContext prismContext); diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerDefinitionImpl.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerDefinitionImpl.java index 60b3b6a8923..12c9f9b71e3 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerDefinitionImpl.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerDefinitionImpl.java @@ -137,21 +137,6 @@ public boolean isAbstract() { return complexTypeDefinition != null && complexTypeDefinition.isAbstract(); } - /** - * Returns true if the definition does not define specific items but it is just - * a "wildcard" for any kind of item (usually represented as xsd:any type). - */ - @Override - public boolean isWildcard() { - if (getTypeName().equals(DOMUtil.XSD_ANY)) { - return true; - } -// if (complexTypeDefinition != null && complexTypeDefinition.isXsdAnyMarker()) { -// return true; -// } - return false; - } - @Override public void revive(PrismContext prismContext) { if (this.prismContext != null) { diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java index 199f7b29970..ff0d62fc5ec 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java @@ -1091,10 +1091,7 @@ public void applyDefinition(@NotNull PrismContainerDefinition containerDef, b return; // there's a definition already } replaceComplexTypeDefinition(containerDef.getComplexTypeDefinition()); - if (complexTypeDefinition == null || complexTypeDefinition.isXsdAnyMarker()) { - // No point in applying this. Nothing will change and there may be phantom errors. - return; - } + // we need to continue even if CTD is null or 'any' - e.g. to resolve definitions within object extension if (items != null) { for (Item item : items) { if (item.getDefinition() != null && !force) { From f5704798b57af100bb06331f7121bfa08fe77cfc Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 2 Nov 2016 11:55:58 +0100 Subject: [PATCH 2/2] Expressions in mext:objectQuery in iterative tasks. --- .../midpoint/schema/TestQueryConvertor.java | 23 +-- .../common/expression/ExpressionUtil.java | 18 ++ .../AbstractSearchIterativeTaskHandler.java | 162 ++++++++++-------- .../model/intest/sync/TestRecomputeTask.java | 65 ++++++- ...sk-user-recompute-herman-by-expression.xml | 52 ++++++ 5 files changed, 228 insertions(+), 92 deletions(-) create mode 100644 model/model-intest/src/test/resources/sync/task-user-recompute-herman-by-expression.xml diff --git a/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestQueryConvertor.java b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestQueryConvertor.java index 65a4833f41b..2639143ecd5 100644 --- a/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestQueryConvertor.java +++ b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestQueryConvertor.java @@ -272,7 +272,7 @@ private PrismObjectDefinition getUserDefinition(){ public void testTypeFilterQuery() throws Exception { displayTestTitle("testConnectorQuery"); SearchFilterType filterType = PrismTestUtil.parseAtomicValue(FILTER_BY_TYPE_FILE, SearchFilterType.COMPLEX_TYPE); - ObjectQuery query = null; + ObjectQuery query; try { query = QueryJaxbConvertor.createObjectQuery(ConnectorType.class, filterType, getPrismContext()); displayQuery(query); @@ -294,12 +294,6 @@ public void testTypeFilterQuery() throws Exception { QueryType convertedQueryType = toQueryType(query); displayQueryType(convertedQueryType); - } catch (SchemaException ex) { - LOGGER.error("Error while converting query: {}", ex.getMessage(), ex); - throw ex; - } catch (RuntimeException ex) { - LOGGER.error("Error while converting query: {}", ex.getMessage(), ex); - throw ex; } catch (Exception ex) { LOGGER.error("Error while converting query: {}", ex.getMessage(), ex); throw ex; @@ -319,15 +313,13 @@ private void assertRefFilterValue(RefFilter filter, String oid) { } private ObjectQuery toObjectQuery(Class type, QueryType queryType) throws Exception { - ObjectQuery query = QueryJaxbConvertor.createObjectQuery(type, queryType, + return QueryJaxbConvertor.createObjectQuery(type, queryType, getPrismContext()); - return query; } private ObjectQuery toObjectQuery(Class type, SearchFilterType filterType) throws Exception { - ObjectQuery query = QueryJaxbConvertor.createObjectQuery(type, filterType, + return QueryJaxbConvertor.createObjectQuery(type, filterType, getPrismContext()); - return query; } private QueryType toQueryType(ObjectQuery query) throws Exception { @@ -386,7 +378,7 @@ public void testUserQuery() throws Exception { for (File file : userQueriesToTest) { SearchFilterType filterType = PrismTestUtil.parseAtomicValue(file, SearchFilterType.COMPLEX_TYPE); LOGGER.info("===[ query type parsed ]==="); - ObjectQuery query = null; + ObjectQuery query; try { query = QueryJaxbConvertor.createObjectQuery(UserType.class, filterType, getPrismContext()); LOGGER.info("query converted: "); @@ -397,12 +389,6 @@ public void testUserQuery() throws Exception { QueryType convertedQueryType = QueryJaxbConvertor.createQueryType(query, getPrismContext()); LOGGER.info(DOMUtil.serializeDOMToString(convertedQueryType.getFilter().getFilterClauseAsElement())); - } catch (SchemaException ex) { - LOGGER.error("Error while converting query: {}", ex.getMessage(), ex); - throw ex; - } catch (RuntimeException ex) { - LOGGER.error("Error while converting query: {}", ex.getMessage(), ex); - throw ex; } catch (Exception ex) { LOGGER.error("Error while converting query: {}", ex.getMessage(), ex); throw ex; @@ -504,7 +490,6 @@ public void test210EqualMultiple() throws Exception { public void test220EqualRightHandItem() throws Exception { final String TEST_NAME = "test220EqualRightHandItem"; displayTestTitle(TEST_NAME); - PrismObjectDefinition userDef = getPrismContext().getSchemaRegistry().findObjectDefinitionByCompileTimeClass(UserType.class); ObjectQuery q = QueryBuilder.queryFor(UserType.class, getPrismContext()) .item(UserType.F_EMPLOYEE_NUMBER).eq().item(UserType.F_COST_CENTER) .build(); diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/ExpressionUtil.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/ExpressionUtil.java index 3c75d305cc9..981aa0fb763 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/ExpressionUtil.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/ExpressionUtil.java @@ -51,6 +51,7 @@ import com.evolveum.midpoint.security.api.SecurityEnforcer; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.DOMUtil; +import com.evolveum.midpoint.util.Holder; import com.evolveum.midpoint.util.PrettyPrinter; import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; @@ -67,6 +68,7 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.QueryInterpretationOfNoValueType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; +import org.jetbrains.annotations.Nullable; /** * @author semancik @@ -470,6 +472,22 @@ public static ObjectFilter evaluateFilterExpressions(ObjectFilter origFilter, shortDesc, task, result); } + public static boolean hasExpressions(@Nullable ObjectFilter filter) { + if (filter == null) { + return false; + } + Holder result = new Holder<>(false); + filter.accept(f -> { + if (f instanceof ValueFilter) { + ValueFilter vf = (ValueFilter) f; + if (vf.getExpression() != null) { + result.setValue(true); + } + } + }); + return result.getValue(); + } + private static ObjectFilter evaluateFilterExpressionsInternal(ObjectFilter filter, ExpressionVariables variables, ExpressionFactory expressionFactory, PrismContext prismContext, String shortDesc, Task task, OperationResult result) diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/util/AbstractSearchIterativeTaskHandler.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/util/AbstractSearchIterativeTaskHandler.java index 3a4795dda5c..232cb19a143 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/util/AbstractSearchIterativeTaskHandler.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/util/AbstractSearchIterativeTaskHandler.java @@ -15,12 +15,15 @@ */ package com.evolveum.midpoint.model.impl.util; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - +import com.evolveum.midpoint.model.common.SystemObjectCache; +import com.evolveum.midpoint.model.common.expression.ExpressionFactory; +import com.evolveum.midpoint.model.common.expression.ExpressionUtil; +import com.evolveum.midpoint.model.common.expression.ExpressionVariables; +import com.evolveum.midpoint.model.impl.ModelObjectResolver; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismProperty; +import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.prism.query.QueryJaxbConvertor; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.GetOperationOptions; @@ -28,33 +31,29 @@ import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.security.api.SecurityEnforcer; -import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; -import com.evolveum.prism.xml.ns._public.query_3.QueryType; - -import org.springframework.beans.factory.annotation.Autowired; - -import com.evolveum.midpoint.model.impl.ModelObjectResolver; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.result.OperationResultStatus; +import com.evolveum.midpoint.security.api.SecurityEnforcer; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.task.api.TaskHandler; import com.evolveum.midpoint.task.api.TaskManager; import com.evolveum.midpoint.task.api.TaskRunResult; import com.evolveum.midpoint.task.api.TaskRunResult.TaskRunResultStatus; -import com.evolveum.midpoint.util.exception.CommunicationException; -import com.evolveum.midpoint.util.exception.ConfigurationException; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SecurityViolationException; +import com.evolveum.midpoint.util.DebugUtil; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; +import com.evolveum.prism.xml.ns._public.query_3.QueryType; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import javax.xml.namespace.QName; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; /** * @author semancik @@ -96,6 +95,12 @@ public abstract class AbstractSearchIterativeTaskHandler type = getType(coordinatorTask); + + try { + // TODO consider which variables should go here (there's no focus, shadow, resource - only configuration) + if (ExpressionUtil.hasExpressions(query.getFilter())) { + PrismObject configuration = systemObjectCache.getSystemConfiguration(opResult); + ExpressionVariables variables = Utils.getDefaultExpressionVariables(null, null, null, + configuration != null ? configuration.asObjectable() : null); + query = ExpressionUtil.evaluateQueryExpressions(query, variables, + expressionFactory, prismContext, "evaluate query expressions", coordinatorTask, opResult); + } + } catch (SchemaException|ObjectNotFoundException|ExpressionEvaluationException e) { + logErrorAndSetResult(runResult, resultHandler, "Error while evaluating expressions in a search filter", e, + OperationResultStatus.FATAL_ERROR, TaskRunResultStatus.PERMANENT_ERROR); + return runResult; + } + + Class type = getType(coordinatorTask); Collection> queryOptions = createQueryOptions(resultHandler, runResult, coordinatorTask, opResult); boolean useRepository = useRepositoryDirectly(resultHandler, runResult, coordinatorTask, opResult); @@ -230,7 +252,7 @@ public TaskRunResult runInternal(Task coordinatorTask) { expectedTotal = (long) expectedTotalInt; // conversion would fail on null } } else { - expectedTotal = Long.valueOf(repositoryService.countObjects(type, query, opResult)); + expectedTotal = (long) repositoryService.countObjects(type, query, opResult); } LOGGER.trace("{}: expecting {} objects to be processed", taskName, expectedTotal); } @@ -254,49 +276,37 @@ public TaskRunResult runInternal(Task coordinatorTask) { } resultHandler.completeProcessing(coordinatorTask, opResult); - } catch (ObjectNotFoundException ex) { - LOGGER.error("{}: Object not found: {}", new Object[]{taskName, ex.getMessage(), ex}); + } catch (ObjectNotFoundException e) { // This is bad. The resource does not exist. Permanent problem. - opResult.recordFatalError("Object not found " + ex.getMessage(), ex); - runResult.setRunResultStatus(TaskRunResultStatus.PERMANENT_ERROR); - runResult.setProgress(resultHandler.getProgress()); + logErrorAndSetResult(runResult, resultHandler, "Object not found", e, + OperationResultStatus.FATAL_ERROR, TaskRunResultStatus.PERMANENT_ERROR); return runResult; - } catch (CommunicationException ex) { - LOGGER.error("{}: Communication error: {}", new Object[]{taskName, ex.getMessage(), ex}); - // Error, but not critical. Just try later. - opResult.recordPartialError("Communication error: " + ex.getMessage(), ex); - runResult.setRunResultStatus(TaskRunResultStatus.TEMPORARY_ERROR); - runResult.setProgress(resultHandler.getProgress()); + } catch (CommunicationException e) { + // Error, but not critical. Just try later. + logErrorAndSetResult(runResult, resultHandler, "Communication error", e, + OperationResultStatus.PARTIAL_ERROR, TaskRunResultStatus.TEMPORARY_ERROR); return runResult; - } catch (SchemaException ex) { - LOGGER.error("{}: Error dealing with schema: {}", new Object[]{taskName, ex.getMessage(), ex}); + } catch (SchemaException e) { // Not sure about this. But most likely it is a misconfigured resource or connector // It may be worth to retry. Error is fatal, but may not be permanent. - opResult.recordFatalError("Error dealing with schema: " + ex.getMessage(), ex); - runResult.setRunResultStatus(TaskRunResultStatus.TEMPORARY_ERROR); - runResult.setProgress(resultHandler.getProgress()); + logErrorAndSetResult(runResult, resultHandler, "Error dealing with schema", e, + OperationResultStatus.FATAL_ERROR, TaskRunResultStatus.TEMPORARY_ERROR); return runResult; - } catch (RuntimeException ex) { - LOGGER.error("{}: Internal Error: {}", new Object[]{taskName, ex.getMessage(), ex}); + } catch (RuntimeException e) { // Can be anything ... but we can't recover from that. // It is most likely a programming error. Does not make much sense to retry. - opResult.recordFatalError("Internal Error: " + ex.getMessage(), ex); - runResult.setRunResultStatus(TaskRunResultStatus.PERMANENT_ERROR); - runResult.setProgress(resultHandler.getProgress()); + logErrorAndSetResult(runResult, resultHandler, "Internal error", e, + OperationResultStatus.FATAL_ERROR, TaskRunResultStatus.PERMANENT_ERROR); return runResult; - } catch (ConfigurationException ex) { - LOGGER.error("{}: Configuration error: {}", new Object[]{taskName, ex.getMessage(), ex}); + } catch (ConfigurationException e) { // Not sure about this. But most likely it is a misconfigured resource or connector // It may be worth to retry. Error is fatal, but may not be permanent. - opResult.recordFatalError("Configuration error: " + ex.getMessage(), ex); - runResult.setRunResultStatus(TaskRunResultStatus.TEMPORARY_ERROR); - runResult.setProgress(resultHandler.getProgress()); + logErrorAndSetResult(runResult, resultHandler, "Configuration error", e, + OperationResultStatus.FATAL_ERROR, TaskRunResultStatus.TEMPORARY_ERROR); return runResult; - } catch (SecurityViolationException ex) { - LOGGER.error("{}: Security violation: {}", new Object[]{taskName, ex.getMessage(), ex}); - opResult.recordFatalError("Security violation: " + ex.getMessage(), ex); - runResult.setRunResultStatus(TaskRunResultStatus.PERMANENT_ERROR); - runResult.setProgress(resultHandler.getProgress()); + } catch (SecurityViolationException e) { + logErrorAndSetResult(runResult, resultHandler, "Security violation", e, + OperationResultStatus.FATAL_ERROR, TaskRunResultStatus.PERMANENT_ERROR); return runResult; } @@ -322,21 +332,29 @@ public TaskRunResult runInternal(Task coordinatorTask) { try { finish(resultHandler, runResult, coordinatorTask, opResult); - } catch (SchemaException ex) { - LOGGER.error("{}: Schema error while finishing the run: {}", new Object[]{taskName, ex.getMessage(), ex}); - opResult.recordFatalError("Schema error while finishing the run: " + ex.getMessage(), ex); - runResult.setRunResultStatus(TaskRunResultStatus.PERMANENT_ERROR); - runResult.setProgress(resultHandler.getProgress()); + } catch (SchemaException e) { + logErrorAndSetResult(runResult, resultHandler, "Schema error while finishing the run", e, + OperationResultStatus.FATAL_ERROR, TaskRunResultStatus.PERMANENT_ERROR); return runResult; } - LOGGER.trace("{} run finished (task {}, run result {})", new Object[]{taskName, coordinatorTask, runResult}); + LOGGER.trace("{} run finished (task {}, run result {})", taskName, coordinatorTask, runResult); return runResult; } - protected void finish(H handler, TaskRunResult runResult, Task task, OperationResult opResult) throws SchemaException { + private TaskRunResult logErrorAndSetResult(TaskRunResult runResult, H resultHandler, String message, Throwable e, + OperationResultStatus opStatus, TaskRunResultStatus status) { + LOGGER.error("{}: {}: {}", taskName, message, e.getMessage(), e); + runResult.getOperationResult().recordStatus(opStatus, message + ": " + e.getMessage(), e); + runResult.setRunResultStatus(status); + runResult.setProgress(resultHandler.getProgress()); + return runResult; + + } + + protected void finish(H handler, TaskRunResult runResult, Task task, OperationResult opResult) throws SchemaException { } private H getHandler(Task task) { @@ -370,7 +388,7 @@ protected T resolveObjectRef(Class type, TaskRunResult objectType = modelObjectResolver.getObject(type, objectOid, null, task, opResult); } catch (ObjectNotFoundException ex) { - LOGGER.error("Import: {} {} not found: {}", new Object[]{typeName, objectOid, ex.getMessage(), ex}); + LOGGER.error("Import: {} {} not found: {}", typeName, objectOid, ex.getMessage(), ex); // This is bad. The resource does not exist. Permanent problem. opResult.recordFatalError(typeName+" not found " + objectOid, ex); runResult.setRunResultStatus(TaskRunResultStatus.PERMANENT_ERROR); @@ -390,17 +408,17 @@ protected T resolveObjectRef(Class type, TaskRunResult runResult.setRunResultStatus(TaskRunResultStatus.PERMANENT_ERROR); return null; } catch (CommunicationException ex) { - LOGGER.error("Import: Error getting {} {}: {}", new Object[]{typeName, objectOid, ex.getMessage(), ex}); + LOGGER.error("Import: Error getting {} {}: {}", typeName, objectOid, ex.getMessage(), ex); opResult.recordFatalError("Error getting "+typeName+" " + objectOid+": "+ex.getMessage(), ex); runResult.setRunResultStatus(TaskRunResultStatus.TEMPORARY_ERROR); return null; } catch (ConfigurationException ex) { - LOGGER.error("Import: Error getting {} {}: {}", new Object[]{typeName, objectOid, ex.getMessage(), ex}); + LOGGER.error("Import: Error getting {} {}: {}", typeName, objectOid, ex.getMessage(), ex); opResult.recordFatalError("Error getting "+typeName+" " + objectOid+": "+ex.getMessage(), ex); runResult.setRunResultStatus(TaskRunResultStatus.PERMANENT_ERROR); return null; } catch (SecurityViolationException ex) { - LOGGER.error("Import: Error getting {} {}: {}", new Object[]{typeName, objectOid, ex.getMessage(), ex}); + LOGGER.error("Import: Error getting {} {}: {}", typeName, objectOid, ex.getMessage(), ex); opResult.recordFatalError("Error getting "+typeName+" " + objectOid+": "+ex.getMessage(), ex); runResult.setRunResultStatus(TaskRunResultStatus.PERMANENT_ERROR); return null; @@ -427,7 +445,7 @@ public void refreshStatus(Task task) { protected abstract ObjectQuery createQuery(H handler, TaskRunResult runResult, Task task, OperationResult opResult) throws SchemaException; // useful e.g. to specify noFetch options for shadow-related queries - private Collection> createQueryOptions(H resultHandler, TaskRunResult runResult, Task coordinatorTask, OperationResult opResult) { + protected Collection> createQueryOptions(H resultHandler, TaskRunResult runResult, Task coordinatorTask, OperationResult opResult) { return null; } diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestRecomputeTask.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestRecomputeTask.java index 7e0cd17a502..3c0dc725d70 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestRecomputeTask.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestRecomputeTask.java @@ -81,6 +81,9 @@ public class TestRecomputeTask extends AbstractInitializedModelIntegrationTest { private static final File TASK_USER_RECOMPUTE_CAPTAIN_FILE = new File(TEST_DIR, "task-user-recompute-captain.xml"); private static final String TASK_USER_RECOMPUTE_CAPTAIN_OID = "91919191-76e0-59e2-86d6-3d4f02d3aaac"; + private static final File TASK_USER_RECOMPUTE_HERMAN_BY_EXPRESSION_FILE = new File(TEST_DIR, "task-user-recompute-herman-by-expression.xml"); + private static final String TASK_USER_RECOMPUTE_HERMAN_BY_EXPRESSION_OID = "91919191-76e0-59e2-86d6-3d4f02d3aadd"; + @Override public void initSystem(Task initTask, OperationResult initResult) throws Exception { super.initSystem(initTask, initResult); @@ -303,5 +306,65 @@ public void test110RecomputeSome() throws Exception { assertUsers(6); } - + + /** + * Here we recompute herman as well. + * + * @throws Exception + */ + @Test + public void test120RecomputeByExpression() throws Exception { + final String TEST_NAME = "test120RecomputeByExpression"; + TestUtil.displayTestTile(this, TEST_NAME); + + // GIVEN + Task task = createTask(TestRecomputeTask.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + // Preconditions + assertUsers(6); + assertDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, "Jack Sparrow", false); + assertDummyAccount(RESOURCE_DUMMY_RED_NAME, USER_HERMAN_USERNAME, "Herman Toothrot", true); + + result.computeStatus(); + TestUtil.assertSuccess(result); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + addObject(TASK_USER_RECOMPUTE_HERMAN_BY_EXPRESSION_FILE); + + dummyAuditService.clear(); + + waitForTaskStart(TASK_USER_RECOMPUTE_HERMAN_BY_EXPRESSION_OID, false); + + // WHEN + TestUtil.displayWhen(TEST_NAME); + + waitForTaskFinish(TASK_USER_RECOMPUTE_HERMAN_BY_EXPRESSION_OID, true, 40000); + + // THEN + TestUtil.displayThen(TEST_NAME); + + List> users = modelService.searchObjects(UserType.class, null, null, task, result); + display("Users after recompute", users); + + assertDummyAccount(null, ACCOUNT_GUYBRUSH_DUMMY_USERNAME, "Guybrush Threepwood", true); + assertDummyAccountAttribute(null, ACCOUNT_GUYBRUSH_DUMMY_USERNAME, + DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_WEAPON_NAME, "cutlass", "dagger"); + assertNoDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_GUYBRUSH_DUMMY_USERNAME); + + // Red resource does not delete accounts on deprovision, it disables them + assertDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, "Jack Sparrow", false); + + // Herman should be recomputed now + assertDummyAccount(RESOURCE_DUMMY_RED_NAME, USER_HERMAN_USERNAME, "Herman Toothrot", false); + + TaskType recomputeTask = getTask(TASK_USER_RECOMPUTE_HERMAN_BY_EXPRESSION_OID).asObjectable(); + assertEquals("Wrong success count", 1, recomputeTask.getOperationStats().getIterativeTaskInformation().getTotalSuccessCount()); + assertEquals("Wrong failure count", 0, recomputeTask.getOperationStats().getIterativeTaskInformation().getTotalFailureCount()); + + assertUsers(6); + + } + } diff --git a/model/model-intest/src/test/resources/sync/task-user-recompute-herman-by-expression.xml b/model/model-intest/src/test/resources/sync/task-user-recompute-herman-by-expression.xml new file mode 100644 index 00000000000..3abc3f3f64f --- /dev/null +++ b/model/model-intest/src/test/resources/sync/task-user-recompute-herman-by-expression.xml @@ -0,0 +1,52 @@ + + + + + + User Recompute: Herman (by expression) + + + + + + name + + + + + + + + + + + runnable + + http://midpoint.evolveum.com/xml/ns/public/model/synchronization/task/recompute/handler-3 + single + tight + +