From a717be80e442b80b43f4e1a356ed66b8b7bf26a6 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Thu, 6 Jul 2017 16:36:28 +0200 Subject: [PATCH] Ability for stricter schema checking for provisioning, better AD tests --- .../RefinedObjectClassDefinitionKey.java | 76 +++++++++++++++++++ .../refinery/RefinedResourceSchemaImpl.java | 25 +++++- .../prism/PrismPropertyDefinition.java | 5 +- .../midpoint/prism/xml/XmlTypeConverter.java | 40 +++++++++- .../schema/util/ResourceTypeUtil.java | 47 ++++++++++++ .../midpoint/schema/util/ShadowUtil.java | 48 +++++++++++- .../xml/ns/public/common/common-core-3.xsd | 16 ++++ .../provisioning/impl/ResourceManager.java | 6 +- .../provisioning/impl/ShadowCache.java | 11 +++ .../AbstractAdLdapMultidomainTest.java | 12 +-- .../testing/conntest/AbstractAdLdapTest.java | 2 +- .../midpoint/testing/conntest/AdUtils.java | 45 +++++++++-- .../ad-ldap-multidomain/resource-chimera.xml | 5 +- 13 files changed, 318 insertions(+), 20 deletions(-) create mode 100644 infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedObjectClassDefinitionKey.java diff --git a/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedObjectClassDefinitionKey.java b/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedObjectClassDefinitionKey.java new file mode 100644 index 00000000000..7b34dc27de4 --- /dev/null +++ b/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedObjectClassDefinitionKey.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 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.common.refinery; + +import javax.xml.namespace.QName; + + +/** + * @author semancik + * + */ +class RefinedObjectClassDefinitionKey { + private QName typeName; + private String intent; + + public RefinedObjectClassDefinitionKey(RefinedObjectClassDefinition rObjectClassDefinition) { + typeName = rObjectClassDefinition.getTypeName(); + intent = rObjectClassDefinition.getIntent(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((intent == null) ? 0 : intent.hashCode()); + result = prime * result + ((typeName == null) ? 0 : typeName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + RefinedObjectClassDefinitionKey other = (RefinedObjectClassDefinitionKey) obj; + if (intent == null) { + if (other.intent != null) { + return false; + } + } else if (!intent.equals(other.intent)) { + return false; + } + if (typeName == null) { + if (other.typeName != null) { + return false; + } + } else if (!typeName.equals(other.typeName)) { + return false; + } + return true; + } + + @Override + public String toString() { + return "(type=" + typeName + ", intent=" + intent + ")"; + } +} diff --git a/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedResourceSchemaImpl.java b/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedResourceSchemaImpl.java index 5b265c2671b..fb7291498e3 100644 --- a/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedResourceSchemaImpl.java +++ b/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedResourceSchemaImpl.java @@ -49,7 +49,7 @@ public class RefinedResourceSchemaImpl implements RefinedResourceSchema { // Original resource schema is there to make parsing easier. // But it is also useful in some cases, e.g. we do not need to pass both refined schema and - // original schema as a metod parameter. + // original schema as a method parameter. private ResourceSchema originalResourceSchema; // This object contains the real data of the refined schema @@ -60,6 +60,12 @@ private RefinedResourceSchemaImpl(@NotNull ResourceSchema originalResourceSchema this.resourceSchema = new ResourceSchemaImpl(originalResourceSchema.getNamespace(), originalResourceSchema.getPrismContext()); } + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public Collection getObjectClassDefinitions() { + return (Collection) getRefinedDefinitions(); + } + @Override public List getRefinedDefinitions() { return resourceSchema.getDefinitions(RefinedObjectClassDefinition.class); @@ -580,4 +586,21 @@ public Collection findTypeDefinitionsB //endregion + public static void validateRefinedSchema(RefinedResourceSchema refinedSchema, PrismObject resource) throws SchemaException { + + Set discrs = new HashSet<>(); + + for (RefinedObjectClassDefinition rObjectClassDefinition: refinedSchema.getRefinedDefinitions()) { + QName typeName = rObjectClassDefinition.getTypeName(); + RefinedObjectClassDefinitionKey key = new RefinedObjectClassDefinitionKey(rObjectClassDefinition); + if (discrs.contains(key)) { + throw new SchemaException("Duplicate definition of object class "+key+" in resource schema of "+resource); + } + discrs.add(key); + + ResourceTypeUtil.validateObjectClassDefinition(rObjectClassDefinition, resource); + } + } + + } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismPropertyDefinition.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismPropertyDefinition.java index a373620fa10..8672deb1bca 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismPropertyDefinition.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismPropertyDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2016 Evolveum + * 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. @@ -70,4 +70,7 @@ default boolean isAnyType() { @NotNull @Override PrismPropertyDefinition clone(); + + @Override + Class getTypeClass(); } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/xml/XmlTypeConverter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/xml/XmlTypeConverter.java index 400e65324fa..bf9b6c0335f 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/xml/XmlTypeConverter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/xml/XmlTypeConverter.java @@ -327,8 +327,46 @@ public static boolean canConvert(Class clazz) { public static boolean canConvert(QName xsdType) { return (XsdTypeMapper.getXsdToJavaMapping(xsdType) != null); } + + public static boolean isMatchingType(Class expectedClass, Class actualClass) { + if (expectedClass.isAssignableFrom(actualClass)) { + return true; + } + if (isMatchingType(expectedClass, actualClass, int.class, Integer.class)) { + return true; + } + if (isMatchingType(expectedClass, actualClass, long.class, Long.class)) { + return true; + } + if (isMatchingType(expectedClass, actualClass, boolean.class, Boolean.class)) { + return true; + } + if (isMatchingType(expectedClass, actualClass, byte.class, Byte.class)) { + return true; + } + if (isMatchingType(expectedClass, actualClass, char.class, Character.class)) { + return true; + } + if (isMatchingType(expectedClass, actualClass, float.class, Float.class)) { + return true; + } + if (isMatchingType(expectedClass, actualClass, double.class, Double.class)) { + return true; + } + return false; + } + + private static boolean isMatchingType(Class expectedClass, Class actualClass, Class lowerClass, Class upperClass) { + if (lowerClass.isAssignableFrom(expectedClass) && upperClass.isAssignableFrom(actualClass)) { + return true; + } + if (lowerClass.isAssignableFrom(actualClass) && upperClass.isAssignableFrom(expectedClass)) { + return true; + } + return false; + } - public static T convertValueElementAsScalar(Element valueElement, Class type) throws SchemaException { + public static T convertValueElementAsScalar(Element valueElement, Class type) throws SchemaException { return toJavaValue(valueElement, type); } diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ResourceTypeUtil.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ResourceTypeUtil.java index 63927333481..d6526c37e2b 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ResourceTypeUtil.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ResourceTypeUtil.java @@ -29,6 +29,7 @@ import org.jetbrains.annotations.Nullable; import org.w3c.dom.Element; +import com.evolveum.midpoint.prism.Definition; import com.evolveum.midpoint.prism.PrismContainer; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismProperty; @@ -36,6 +37,9 @@ import com.evolveum.midpoint.schema.CapabilityUtil; import com.evolveum.midpoint.schema.constants.MidPointConstants; import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition; +import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; +import com.evolveum.midpoint.schema.processor.ResourceSchema; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; @@ -648,4 +652,47 @@ public static ShadowCheckType getShadowConstaintsCheck(ResourceType resource) { } return shadowCheckType; } + + public static boolean isValidateSchema(ResourceType resource) { + ResourceConsistencyType consistency = resource.getConsistency(); + if (consistency == null) { + return false; + } + return Boolean.TRUE.equals(consistency.isValidateSchema()); + } + + // TODO: maybe later move to ResourceSchema? + public static void validateSchema(ResourceSchema resourceSchema, PrismObject resource) throws SchemaException { + + Set objectClassNames = new HashSet<>(); + + for (ObjectClassComplexTypeDefinition objectClassDefinition: resourceSchema.getObjectClassDefinitions()) { + QName typeName = objectClassDefinition.getTypeName(); + if (objectClassNames.contains(typeName)) { + throw new SchemaException("Duplicate definition of object class "+typeName+" in resource schema of "+resource); + } + objectClassNames.add(typeName); + + validateObjectClassDefinition(objectClassDefinition, resource); + } + } + + public static void validateObjectClassDefinition(ObjectClassComplexTypeDefinition objectClassDefinition, + PrismObject resource) throws SchemaException { + Set attributeNames = new HashSet<>(); + for (ResourceAttributeDefinition attributeDefinition: objectClassDefinition.getAttributeDefinitions()) { + QName attrName = attributeDefinition.getName(); + if (attributeNames.contains(attrName)) { + throw new SchemaException("Duplicate definition of attribute "+attrName+" in object class "+objectClassDefinition.getTypeName()+" in resource schema of "+resource); + } + attributeNames.add(attrName); + } + + Collection> primaryIdentifiers = objectClassDefinition.getPrimaryIdentifiers(); + Collection> secondaryIdentifiers = objectClassDefinition.getSecondaryIdentifiers(); + + if (primaryIdentifiers.isEmpty() && secondaryIdentifiers.isEmpty()) { + throw new SchemaException("No identifiers in definition of object class "+objectClassDefinition.getTypeName()+" in resource schema of "+resource); + } + } } diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ShadowUtil.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ShadowUtil.java index df7c48de327..231ecd87c74 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ShadowUtil.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ShadowUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2016 Evolveum + * 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. @@ -20,6 +20,7 @@ import com.evolveum.midpoint.prism.path.ItemPathSegment; import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.prism.xml.XmlTypeConverter; import com.evolveum.midpoint.schema.ResourceShadowDiscriminator; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.processor.*; @@ -27,6 +28,8 @@ import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.exception.SystemException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; @@ -46,6 +49,8 @@ */ public class ShadowUtil { + private static final Trace LOGGER = TraceManager.getTrace(ShadowUtil.class); + public static Collection> getPrimaryIdentifiers(ShadowType shadowType) { return getPrimaryIdentifiers(shadowType.asPrismObject()); } @@ -710,4 +715,45 @@ public static ResourceAttribute fixAttributePath(ResourceAttribute attribu return fixedAttribute; } + // TODO: may be useful to move to ObjectClassComplexTypeDefinition later? + public static void validateAttributeSchema(PrismObject shadow, + ObjectClassComplexTypeDefinition objectClassDefinition) throws SchemaException { + ResourceAttributeContainer attributesContainer = getAttributesContainer(shadow); + for (ResourceAttribute attribute: attributesContainer.getAttributes()) { + validateAttribute(attribute, objectClassDefinition); + } + } + + // TODO: may be useful to move to ResourceAttributeDefinition later? + private static void validateAttribute(ResourceAttribute attribute, + ObjectClassComplexTypeDefinition objectClassDefinition) throws SchemaException { + QName attrName = attribute.getElementName(); + ResourceAttributeDefinition attrDef = objectClassDefinition.findAttributeDefinition(attrName); + if (attrDef == null) { + throw new SchemaException("No definition for attribute "+attrName+" in object class "+objectClassDefinition); + } + List> pvals = attribute.getValues(); + if (pvals == null || pvals.isEmpty()) { + if (attrDef.isMandatory()) { + throw new SchemaException("Mandatory attribute "+attrName+" has no value"); + } else { + return; + } + } + if (pvals.size() > 1 && attrDef.isSingleValue()) { + throw new SchemaException("Single-value attribute "+attrName+" has "+pvals.size()+" values"); + } + Class expectedClass = attrDef.getTypeClass(); + for (PrismPropertyValue pval: pvals) { + T val = pval.getValue(); + if (val == null) { + throw new SchemaException("Null value in attribute "+attrName); + } + LOGGER.info("MMMMMMMMMMMM: {}:{}\n {} <-> {}", attrName, attrDef, expectedClass, val.getClass()); + if (!XmlTypeConverter.isMatchingType(expectedClass, val.getClass())) { + throw new SchemaException("Wrong value in attribute "+attrName+"; expected class "+attrDef.getTypeClass().getSimpleName()+", but was "+val.getClass()); + } + } + } + } diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd index a2873f28dfb..81f6fb72658 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd @@ -4432,6 +4432,22 @@ + + + + If set to true then midPoint will validate the schema of objects that leave + and enter midPoint by the connectors. MidPoint will checks if datatypes and + multiplicity is correct and issue hard errors in any mismatch. + + EXPERIMENTAL: this feature is used mostly for internal checks during + development and testing. It is not intended for production use. + Those checks may slow the system down and they may also may impact + robustness. MidPoint is usually able to deal data types that are slightly + wrong and auto-correct them. Enabling this feature will cause that an error + is thrown even if cases that may get auto-corrected. + + + diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceManager.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceManager.java index 85e73f30742..18f07aa26a2 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceManager.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceManager.java @@ -667,7 +667,11 @@ private ResourceSchema fetchResourceSchema(PrismObject resource, M List generateObjectClasses = ResourceTypeUtil.getSchemaGenerationConstraints(resource); ConnectorInstance connectorInstance = connectorManager.getConfiguredConnectorInstance(connectorSpec, false, parentResult); LOGGER.trace("Trying to get schema from {}", connectorSpec); - return connectorInstance.fetchResourceSchema(generateObjectClasses, parentResult); + ResourceSchema resourceSchema = connectorInstance.fetchResourceSchema(generateObjectClasses, parentResult); + if (ResourceTypeUtil.isValidateSchema(resource.asObjectable())) { + ResourceTypeUtil.validateSchema(resourceSchema, resource); + } + return resourceSchema; } diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java index 5ad6db8c572..d1dda1f3be8 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java @@ -621,6 +621,11 @@ public String addShadow(PrismObject shadow, OperationProvisioningScr } private void preAddChecks(ProvisioningContext ctx, PrismObject shadow, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException, ObjectAlreadyExistsException, SecurityViolationException { + checkConstraints(ctx, shadow, task, result); + validateSchema(ctx, shadow, task, result); + } + + private void checkConstraints(ProvisioningContext ctx, PrismObject shadow, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException, ObjectAlreadyExistsException, SecurityViolationException { ShadowCheckType shadowConstraintsCheck = ResourceTypeUtil.getShadowConstaintsCheck(ctx.getResource()); if (shadowConstraintsCheck == ShadowCheckType.NONE) { return; @@ -645,6 +650,12 @@ private void preAddChecks(ProvisioningContext ctx, PrismObject shado throw new ObjectAlreadyExistsException("Conflicting shadow already exists on "+ctx.getResource()); } } + + private void validateSchema(ProvisioningContext ctx, PrismObject shadow, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException, ObjectAlreadyExistsException, SecurityViolationException { + if (ResourceTypeUtil.isValidateSchema(ctx.getResource())) { + ShadowUtil.validateAttributeSchema(shadow, ctx.getObjectClassDefinition()); + } + } private ResourceOperationDescription createSuccessOperationDescription(ProvisioningContext ctx, PrismObject shadowType, ObjectDelta delta, OperationResult parentResult) diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapMultidomainTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapMultidomainTest.java index f0e681b7a74..6ea5dd5285e 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapMultidomainTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapMultidomainTest.java @@ -56,6 +56,7 @@ import com.evolveum.midpoint.schema.SearchResultMetadata; import com.evolveum.midpoint.schema.constants.MidPointConstants; import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.internals.InternalCounters; import com.evolveum.midpoint.schema.processor.ResourceAttribute; import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; import com.evolveum.midpoint.schema.processor.ResourceSchema; @@ -329,8 +330,9 @@ public void test020Schema() throws Exception { displayTestTile(TEST_NAME); // IntegrationTestTools.displayXml("Resource XML", resource); - accountObjectClassDefinition = AdUtils.assertAdSchema(resource, getAccountObjectClass(), prismContext); - AdUtils.assertExchangeSchema(resource, prismContext); + accountObjectClassDefinition = AdUtils.assertAdResourceSchema(resource, getAccountObjectClass(), prismContext); + AdUtils.assertAdRefinedSchema(resource, getAccountObjectClass(), prismContext); + AdUtils.assertExchangeSchema(resource, getAccountObjectClass(), prismContext); ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); assertEquals("Unexpected number of schema definitions (limited by generation constraints)", 5, resourceSchema.getDefinitions().size()); @@ -349,8 +351,8 @@ public void test100SeachJackBySamAccountName() throws Exception { ObjectQuery query = createSamAccountNameQuery(ACCOUNT_JACK_SAM_ACCOUNT_NAME); - rememberConnectorOperationCount(); - rememberConnectorSimulatedPagingSearchCount(); + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); // WHEN displayWhen(TEST_NAME); @@ -369,7 +371,7 @@ public void test100SeachJackBySamAccountName() throws Exception { jackAccountOid = shadow.getOid(); // assertConnectorOperationIncrement(2); - assertConnectorSimulatedPagingSearchIncrement(0); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); SearchResultMetadata metadata = shadows.getMetadata(); if (metadata != null) { diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapTest.java index 5cb03db6113..6ad026fead6 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractAdLdapTest.java @@ -263,7 +263,7 @@ public void test020Schema() throws Exception { final String TEST_NAME = "test020Schema"; TestUtil.displayTestTile(this, TEST_NAME); - accountObjectClassDefinition = AdUtils.assertAdSchema(resource, getAccountObjectClass(), prismContext); + accountObjectClassDefinition = AdUtils.assertAdResourceSchema(resource, getAccountObjectClass(), prismContext); assertLdapConnectorInstances(1); } diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AdUtils.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AdUtils.java index 15c4aad737c..afd4913b690 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AdUtils.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AdUtils.java @@ -23,6 +23,7 @@ import javax.xml.namespace.QName; import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; +import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.util.PrismAsserts; @@ -30,6 +31,7 @@ import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition; import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; import com.evolveum.midpoint.schema.processor.ResourceSchema; +import com.evolveum.midpoint.schema.util.ResourceTypeUtil; import com.evolveum.midpoint.test.IntegrationTestTools; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.exception.SchemaException; @@ -78,10 +80,24 @@ public static String formatGuidToDashedNotation(String hexValue) { return sb.toString(); } - public static ObjectClassComplexTypeDefinition assertAdSchema(PrismObject resource, QName accountObjectClass, PrismContext prismContext) throws SchemaException { - - ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); - display("Resource schema", resourceSchema); + public static ObjectClassComplexTypeDefinition assertAdResourceSchema(PrismObject resource, QName accountObjectClass, PrismContext prismContext) throws SchemaException { + ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); + display("Resource schema", resourceSchema); + ResourceTypeUtil.validateSchema(resourceSchema, resource); + ObjectClassComplexTypeDefinition accountObjectClassDef = assertAdSchema(resourceSchema, resource, accountObjectClass, prismContext); + return accountObjectClassDef; + } + + public static ObjectClassComplexTypeDefinition assertAdRefinedSchema(PrismObject resource, QName accountObjectClass, PrismContext prismContext) throws SchemaException { + RefinedResourceSchema refinedSchema = RefinedResourceSchema.getRefinedSchema(resource); + display("Refined schema", refinedSchema); + RefinedResourceSchemaImpl.validateRefinedSchema(refinedSchema, resource); + ObjectClassComplexTypeDefinition accountObjectClassDef = assertAdSchema(refinedSchema, resource, accountObjectClass, prismContext); + return accountObjectClassDef; + } + + public static ObjectClassComplexTypeDefinition assertAdSchema(ResourceSchema resourceSchema, PrismObject resource, QName accountObjectClass, PrismContext prismContext) throws SchemaException { + RefinedResourceSchema refinedSchema = RefinedResourceSchema.getRefinedSchema(resource); display("Refined schema", refinedSchema); @@ -139,11 +155,17 @@ public static ObjectClassComplexTypeDefinition assertAdSchema(PrismObject resource, PrismContext prismContext) throws SchemaException { + public static void assertExchangeSchema(PrismObject resource, QName accountObjectClassQName, PrismContext prismContext) throws SchemaException { ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); + assertExchangeSchema(resourceSchema, resource, accountObjectClassQName, prismContext); - ObjectClassComplexTypeDefinition msExchBaseClassObjectClassDefinition = resourceSchema.findObjectClassDefinition(OBJECT_CLASS_MS_EXCH_BASE_CLASS_QNAME); + RefinedResourceSchema refinedSchema = RefinedResourceSchema.getRefinedSchema(resource); + assertExchangeSchema(refinedSchema, resource, accountObjectClassQName, prismContext); + } + + public static void assertExchangeSchema(ResourceSchema resourceSchema, PrismObject resource, QName accountObjectClassQName, PrismContext prismContext) throws SchemaException { + ObjectClassComplexTypeDefinition msExchBaseClassObjectClassDefinition = resourceSchema.findObjectClassDefinition(OBJECT_CLASS_MS_EXCH_BASE_CLASS_QNAME); assertNotNull("No definition for object class "+OBJECT_CLASS_MS_EXCH_BASE_CLASS_QNAME, msExchBaseClassObjectClassDefinition); display("Object class "+OBJECT_CLASS_MS_EXCH_BASE_CLASS_QNAME+" def", msExchBaseClassObjectClassDefinition); @@ -152,7 +174,16 @@ public static void assertExchangeSchema(PrismObject resource, Pris assertTrue("msExchHideFromAddressLists read", msExchHideFromAddressListsDef.canRead()); assertTrue("msExchHideFromAddressLists modify", msExchHideFromAddressListsDef.canModify()); assertTrue("msExchHideFromAddressLists add", msExchHideFromAddressListsDef.canAdd()); - + + ObjectClassComplexTypeDefinition accountObjectClassDef = resourceSchema.findObjectClassDefinition(accountObjectClassQName); + assertNotNull("No definition for object class "+accountObjectClassQName, accountObjectClassDef); + display("Object class "+accountObjectClassQName+" def", accountObjectClassDef); + + ResourceAttributeDefinition accountMsExchHideFromAddressListsDef = accountObjectClassDef.findAttributeDefinition(ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME); + PrismAsserts.assertDefinition(accountMsExchHideFromAddressListsDef, new QName(MidPointConstants.NS_RI, ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME), DOMUtil.XSD_BOOLEAN, 0, 1); + assertTrue("msExchHideFromAddressLists read", accountMsExchHideFromAddressListsDef.canRead()); + assertTrue("msExchHideFromAddressLists modify", accountMsExchHideFromAddressListsDef.canModify()); + assertTrue("msExchHideFromAddressLists add", accountMsExchHideFromAddressListsDef.canAdd()); } } diff --git a/testing/conntest/src/test/resources/ad-ldap-multidomain/resource-chimera.xml b/testing/conntest/src/test/resources/ad-ldap-multidomain/resource-chimera.xml index 1b444dd860f..8943e733e20 100644 --- a/testing/conntest/src/test/resources/ad-ldap-multidomain/resource-chimera.xml +++ b/testing/conntest/src/test/resources/ad-ldap-multidomain/resource-chimera.xml @@ -241,9 +241,9 @@ @@ -758,6 +758,7 @@ true + true