use of org.identityconnectors.framework.common.objects.ObjectClass in project midpoint by Evolveum.
the class ConnectorInstanceConnIdImpl method fetchCurrentToken.
@Override
public <T> PrismProperty<T> fetchCurrentToken(ObjectClassComplexTypeDefinition objectClassDef, StateReporter reporter, OperationResult parentResult) throws CommunicationException, GenericFrameworkException {
OperationResult result = parentResult.createSubresult(ConnectorInstance.class.getName() + ".fetchCurrentToken");
result.addParam("objectClass", objectClassDef);
ObjectClass icfObjectClass;
if (objectClassDef == null) {
icfObjectClass = ObjectClass.ALL;
} else {
icfObjectClass = connIdNameMapper.objectClassToIcf(objectClassDef, getSchemaNamespace(), connectorType, legacySchema);
}
OperationResult icfResult = result.createSubresult(ConnectorFacade.class.getName() + ".sync");
icfResult.addContext("connector", connIdConnectorFacade.getClass());
icfResult.addArbitraryObjectAsParam("icfObjectClass", icfObjectClass);
SyncToken syncToken = null;
try {
InternalMonitor.recordConnectorOperation("getLatestSyncToken");
recordIcfOperationStart(reporter, ProvisioningOperation.ICF_GET_LATEST_SYNC_TOKEN, objectClassDef);
syncToken = connIdConnectorFacade.getLatestSyncToken(icfObjectClass);
recordIcfOperationEnd(reporter, ProvisioningOperation.ICF_GET_LATEST_SYNC_TOKEN, objectClassDef);
icfResult.recordSuccess();
icfResult.addReturn("syncToken", syncToken == null ? null : String.valueOf(syncToken.getValue()));
} catch (Throwable ex) {
recordIcfOperationEnd(reporter, ProvisioningOperation.ICF_GET_LATEST_SYNC_TOKEN, objectClassDef, ex);
Throwable midpointEx = processIcfException(ex, this, icfResult);
result.computeStatus();
// exception
if (midpointEx instanceof CommunicationException) {
throw (CommunicationException) midpointEx;
} else if (midpointEx instanceof GenericFrameworkException) {
throw (GenericFrameworkException) midpointEx;
} else if (midpointEx instanceof RuntimeException) {
throw (RuntimeException) midpointEx;
} else if (midpointEx instanceof Error) {
throw (Error) midpointEx;
} else {
throw new SystemException("Got unexpected exception: " + ex.getClass().getName() + ": " + ex.getMessage(), ex);
}
}
if (syncToken == null) {
result.recordWarning("Resource have not provided a current sync token");
return null;
}
PrismProperty<T> property = getToken(syncToken);
result.recordSuccess();
return property;
}
use of org.identityconnectors.framework.common.objects.ObjectClass in project midpoint by Evolveum.
the class ConnectorInstanceConnIdImpl method modifyObject.
// TODO [med] beware, this method does not obey its contract specified in the interface
// (1) currently it does not return all the changes, only the 'side effect' changes
// (2) it throws exceptions even if some of the changes were made
// (3) among identifiers, only the UID value is updated on object rename
// (other identifiers are ignored on input and output of this method)
@Override
public AsynchronousOperationReturnValue<Collection<PropertyModificationOperation>> modifyObject(ObjectClassComplexTypeDefinition objectClassDef, Collection<? extends ResourceAttribute<?>> identifiers, Collection<Operation> changes, StateReporter reporter, OperationResult parentResult) throws ObjectNotFoundException, CommunicationException, GenericFrameworkException, SchemaException, SecurityViolationException, ObjectAlreadyExistsException {
OperationResult result = parentResult.createSubresult(ConnectorInstance.class.getName() + ".modifyObject");
result.addParam("objectClass", objectClassDef);
result.addCollectionOfSerializablesAsParam("identifiers", identifiers);
result.addArbitraryCollectionAsParam("changes", changes);
if (changes.isEmpty()) {
LOGGER.info("No modifications for connector object specified. Skipping processing.");
result.recordNotApplicableIfUnknown();
return AsynchronousOperationReturnValue.wrap(new ArrayList<PropertyModificationOperation>(0), result);
}
ObjectClass objClass = connIdNameMapper.objectClassToIcf(objectClassDef, getSchemaNamespace(), connectorType, legacySchema);
Uid uid;
try {
uid = getUid(objectClassDef, identifiers);
} catch (SchemaException e) {
result.recordFatalError(e);
throw e;
}
if (uid == null) {
result.recordFatalError("Cannot detemine UID from identifiers: " + identifiers);
throw new IllegalArgumentException("Cannot detemine UID from identifiers: " + identifiers);
}
String originalUid = uid.getUidValue();
Set<Attribute> attributesToAdd = new HashSet<>();
Set<Attribute> attributesToUpdate = new HashSet<>();
Set<Attribute> attributesToRemove = new HashSet<>();
Set<Operation> additionalOperations = new HashSet<Operation>();
PasswordChangeOperation passwordChangeOperation = null;
Collection<PropertyDelta<?>> activationDeltas = new HashSet<PropertyDelta<?>>();
PropertyDelta<ProtectedStringType> passwordDelta = null;
PropertyDelta<QName> auxiliaryObjectClassDelta = null;
for (Operation operation : changes) {
if (operation == null) {
IllegalArgumentException e = new IllegalArgumentException("Null operation in modifyObject");
result.recordFatalError(e);
throw e;
}
if (operation instanceof PropertyModificationOperation) {
PropertyDelta<?> delta = ((PropertyModificationOperation) operation).getPropertyDelta();
if (delta.getPath().equivalent(new ItemPath(ShadowType.F_AUXILIARY_OBJECT_CLASS))) {
auxiliaryObjectClassDelta = (PropertyDelta<QName>) delta;
}
}
}
try {
ObjectClassComplexTypeDefinition structuralObjectClassDefinition = resourceSchema.findObjectClassDefinition(objectClassDef.getTypeName());
if (structuralObjectClassDefinition == null) {
throw new SchemaException("No definition of structural object class " + objectClassDef.getTypeName() + " in " + description);
}
Map<QName, ObjectClassComplexTypeDefinition> auxiliaryObjectClassMap = new HashMap<>();
if (auxiliaryObjectClassDelta != null) {
// Activation change means modification of attributes
if (auxiliaryObjectClassDelta.isReplace()) {
if (auxiliaryObjectClassDelta.getValuesToReplace() == null || auxiliaryObjectClassDelta.getValuesToReplace().isEmpty()) {
attributesToUpdate.add(AttributeBuilder.build(PredefinedAttributes.AUXILIARY_OBJECT_CLASS_NAME));
} else {
addConvertedValues(auxiliaryObjectClassDelta.getValuesToReplace(), attributesToUpdate, auxiliaryObjectClassMap);
}
} else {
addConvertedValues(auxiliaryObjectClassDelta.getValuesToAdd(), attributesToAdd, auxiliaryObjectClassMap);
addConvertedValues(auxiliaryObjectClassDelta.getValuesToDelete(), attributesToRemove, auxiliaryObjectClassMap);
}
}
for (Operation operation : changes) {
if (operation instanceof PropertyModificationOperation) {
PropertyModificationOperation change = (PropertyModificationOperation) operation;
PropertyDelta<?> delta = change.getPropertyDelta();
if (delta.getParentPath().equivalent(new ItemPath(ShadowType.F_ATTRIBUTES))) {
if (delta.getDefinition() == null || !(delta.getDefinition() instanceof ResourceAttributeDefinition)) {
ResourceAttributeDefinition def = objectClassDef.findAttributeDefinition(delta.getElementName());
if (def == null) {
String message = "No definition for attribute " + delta.getElementName() + " used in modification delta";
result.recordFatalError(message);
throw new SchemaException(message);
}
try {
delta.applyDefinition(def);
} catch (SchemaException e) {
result.recordFatalError(e.getMessage(), e);
throw e;
}
}
boolean isInRemovedAuxClass = false;
boolean isInAddedAuxClass = false;
ResourceAttributeDefinition<Object> structAttrDef = structuralObjectClassDefinition.findAttributeDefinition(delta.getElementName());
// aux object class, we cannot add/remove it with the object class unless it is normally requested
if (structAttrDef == null) {
if (auxiliaryObjectClassDelta != null && auxiliaryObjectClassDelta.isDelete()) {
// is removed, the attributes must be removed as well.
for (PrismPropertyValue<QName> auxPval : auxiliaryObjectClassDelta.getValuesToDelete()) {
ObjectClassComplexTypeDefinition auxDef = auxiliaryObjectClassMap.get(auxPval.getValue());
ResourceAttributeDefinition<Object> attrDef = auxDef.findAttributeDefinition(delta.getElementName());
if (attrDef != null) {
isInRemovedAuxClass = true;
break;
}
}
}
if (auxiliaryObjectClassDelta != null && auxiliaryObjectClassDelta.isAdd()) {
// is added, the attributes must be added as well.
for (PrismPropertyValue<QName> auxPval : auxiliaryObjectClassDelta.getValuesToAdd()) {
ObjectClassComplexTypeDefinition auxOcDef = auxiliaryObjectClassMap.get(auxPval.getValue());
ResourceAttributeDefinition<Object> auxAttrDef = auxOcDef.findAttributeDefinition(delta.getElementName());
if (auxAttrDef != null) {
isInAddedAuxClass = true;
break;
}
}
}
}
// Change in (ordinary) attributes. Transform to the ConnId attributes.
if (delta.isAdd()) {
ResourceAttribute<?> mpAttr = (ResourceAttribute<?>) delta.instantiateEmptyProperty();
mpAttr.addValues((Collection) PrismValue.cloneCollection(delta.getValuesToAdd()));
Attribute connIdAttr = connIdConvertor.convertToConnIdAttribute(mpAttr, objectClassDef);
if (mpAttr.getDefinition().isMultiValue()) {
attributesToAdd.add(connIdAttr);
} else {
// Force "update" for single-valued attributes instead of "add". This is saving one
// read in some cases. It should also make no substantial difference in such case.
// But it is working around some connector bugs.
attributesToUpdate.add(connIdAttr);
}
}
if (delta.isDelete()) {
ResourceAttribute<?> mpAttr = (ResourceAttribute<?>) delta.instantiateEmptyProperty();
if (mpAttr.getDefinition().isMultiValue() || isInRemovedAuxClass) {
mpAttr.addValues((Collection) PrismValue.cloneCollection(delta.getValuesToDelete()));
Attribute connIdAttr = connIdConvertor.convertToConnIdAttribute(mpAttr, objectClassDef);
attributesToRemove.add(connIdAttr);
} else {
// Force "update" for single-valued attributes instead of "add". This is saving one
// read in some cases.
// Update attribute to no values. This will efficiently clean up the attribute.
// It should also make no substantial difference in such case.
// But it is working around some connector bugs.
Attribute connIdAttr = connIdConvertor.convertToConnIdAttribute(mpAttr, objectClassDef);
// update with EMTPY value. The mpAttr.addValues() is NOT in this branch
attributesToUpdate.add(connIdAttr);
}
}
if (delta.isReplace()) {
ResourceAttribute<?> mpAttr = (ResourceAttribute<?>) delta.instantiateEmptyProperty();
mpAttr.addValues((Collection) PrismValue.cloneCollection(delta.getValuesToReplace()));
Attribute connIdAttr = connIdConvertor.convertToConnIdAttribute(mpAttr, objectClassDef);
if (isInAddedAuxClass) {
attributesToAdd.add(connIdAttr);
} else {
attributesToUpdate.add(connIdAttr);
}
}
} else if (delta.getParentPath().equivalent(new ItemPath(ShadowType.F_ACTIVATION))) {
activationDeltas.add(delta);
} else if (delta.getParentPath().equivalent(new ItemPath(new ItemPath(ShadowType.F_CREDENTIALS), CredentialsType.F_PASSWORD))) {
passwordDelta = (PropertyDelta<ProtectedStringType>) delta;
} else if (delta.getPath().equivalent(new ItemPath(ShadowType.F_AUXILIARY_OBJECT_CLASS))) {
// already processed
} else {
throw new SchemaException("Change of unknown attribute " + delta.getPath());
}
} else if (operation instanceof PasswordChangeOperation) {
passwordChangeOperation = (PasswordChangeOperation) operation;
// TODO: check for multiple occurrences and fail
} else if (operation instanceof ExecuteProvisioningScriptOperation) {
ExecuteProvisioningScriptOperation scriptOperation = (ExecuteProvisioningScriptOperation) operation;
additionalOperations.add(scriptOperation);
} else {
throw new IllegalArgumentException("Unknown operation type " + operation.getClass().getName() + ": " + operation);
}
}
} catch (SchemaException | RuntimeException e) {
result.recordFatalError(e);
throw e;
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("attributes:\nADD: {}\nUPDATE: {}\nREMOVE: {}", attributesToAdd, attributesToUpdate, attributesToRemove);
}
// Needs three complete try-catch blocks because we need to create
// icfResult for each operation
// and handle the faults individually
checkAndExecuteAdditionalOperation(reporter, additionalOperations, BeforeAfterType.BEFORE, result);
OperationResult connIdResult = null;
try {
if (!attributesToAdd.isEmpty()) {
OperationOptions options = new OperationOptionsBuilder().build();
connIdResult = result.createSubresult(ConnectorFacade.class.getName() + ".addAttributeValues");
connIdResult.addParam("objectClass", objectClassDef);
connIdResult.addParam("uid", uid.getUidValue());
connIdResult.addArbitraryCollectionAsParam("attributes", attributesToAdd);
connIdResult.addArbitraryObjectAsParam("options", options);
connIdResult.addContext("connector", connIdConnectorFacade.getClass());
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Invoking ICF addAttributeValues(), objectclass={}, uid={}, attributes: {}", new Object[] { objClass, uid, dumpAttributes(attributesToAdd) });
}
InternalMonitor.recordConnectorOperation("addAttributeValues");
// Invoking ConnId
recordIcfOperationStart(reporter, ProvisioningOperation.ICF_UPDATE, objectClassDef, uid);
uid = connIdConnectorFacade.addAttributeValues(objClass, uid, attributesToAdd, options);
recordIcfOperationEnd(reporter, ProvisioningOperation.ICF_UPDATE, objectClassDef, null, uid);
connIdResult.recordSuccess();
}
} catch (Throwable ex) {
recordIcfOperationEnd(reporter, ProvisioningOperation.ICF_UPDATE, objectClassDef, ex, uid);
String desc = this.getHumanReadableName() + " while adding attribute values to object identified by ICF UID '" + uid.getUidValue() + "'";
Throwable midpointEx = processIcfException(ex, desc, connIdResult);
result.computeStatus("Adding attribute values failed");
// exception
if (midpointEx instanceof ObjectNotFoundException) {
throw (ObjectNotFoundException) midpointEx;
} else if (midpointEx instanceof CommunicationException) {
//in this situation this is not a critical error, becasue we know to handle it..so mute the error and sign it as expected
result.muteError();
connIdResult.muteError();
throw (CommunicationException) midpointEx;
} else if (midpointEx instanceof GenericFrameworkException) {
throw (GenericFrameworkException) midpointEx;
} else if (midpointEx instanceof SchemaException) {
throw (SchemaException) midpointEx;
} else if (midpointEx instanceof AlreadyExistsException) {
throw (AlreadyExistsException) midpointEx;
} else if (midpointEx instanceof RuntimeException) {
throw (RuntimeException) midpointEx;
} else if (midpointEx instanceof SecurityViolationException) {
throw (SecurityViolationException) midpointEx;
} else if (midpointEx instanceof Error) {
throw (Error) midpointEx;
} else {
throw new SystemException("Got unexpected exception: " + ex.getClass().getName() + ": " + ex.getMessage(), ex);
}
}
if (!attributesToUpdate.isEmpty() || activationDeltas != null || passwordDelta != null || auxiliaryObjectClassDelta != null) {
try {
if (activationDeltas != null) {
// Activation change means modification of attributes
convertFromActivation(attributesToUpdate, activationDeltas);
}
if (passwordDelta != null) {
// Activation change means modification of attributes
convertFromPassword(attributesToUpdate, passwordDelta);
}
} catch (SchemaException ex) {
result.recordFatalError("Error while converting resource object attributes. Reason: " + ex.getMessage(), ex);
throw new SchemaException("Error while converting resource object attributes. Reason: " + ex.getMessage(), ex);
} catch (RuntimeException ex) {
result.recordFatalError("Error while converting resource object attributes. Reason: " + ex.getMessage(), ex);
throw ex;
}
if (!attributesToUpdate.isEmpty()) {
OperationOptions options = new OperationOptionsBuilder().build();
connIdResult = result.createSubresult(ConnectorFacade.class.getName() + ".update");
connIdResult.addParam("objectClass", objectClassDef);
connIdResult.addParam("uid", uid == null ? "null" : uid.getUidValue());
connIdResult.addArbitraryCollectionAsParam("attributes", attributesToUpdate);
connIdResult.addArbitraryObjectAsParam("options", options);
connIdResult.addContext("connector", connIdConnectorFacade.getClass());
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Invoking ICF update(), objectclass={}, uid={}, attributes: {}", new Object[] { objClass, uid, dumpAttributes(attributesToUpdate) });
}
try {
// Call ICF
InternalMonitor.recordConnectorOperation("update");
recordIcfOperationStart(reporter, ProvisioningOperation.ICF_UPDATE, objectClassDef, uid);
uid = connIdConnectorFacade.update(objClass, uid, attributesToUpdate, options);
recordIcfOperationEnd(reporter, ProvisioningOperation.ICF_UPDATE, objectClassDef, null, uid);
connIdResult.recordSuccess();
} catch (Throwable ex) {
recordIcfOperationEnd(reporter, ProvisioningOperation.ICF_UPDATE, objectClassDef, ex, uid);
String desc = this.getHumanReadableName() + " while updating object identified by ICF UID '" + uid.getUidValue() + "'";
Throwable midpointEx = processIcfException(ex, desc, connIdResult);
result.computeStatus("Update failed");
// exception
if (midpointEx instanceof ObjectNotFoundException) {
throw (ObjectNotFoundException) midpointEx;
} else if (midpointEx instanceof CommunicationException) {
//in this situation this is not a critical error, becasue we know to handle it..so mute the error and sign it as expected
result.muteError();
connIdResult.muteError();
throw (CommunicationException) midpointEx;
} else if (midpointEx instanceof GenericFrameworkException) {
throw (GenericFrameworkException) midpointEx;
} else if (midpointEx instanceof SchemaException) {
throw (SchemaException) midpointEx;
} else if (midpointEx instanceof ObjectAlreadyExistsException) {
throw (ObjectAlreadyExistsException) midpointEx;
} else if (midpointEx instanceof RuntimeException) {
throw (RuntimeException) midpointEx;
} else if (midpointEx instanceof SecurityViolationException) {
throw (SecurityViolationException) midpointEx;
} else if (midpointEx instanceof Error) {
throw (Error) midpointEx;
} else {
throw new SystemException("Got unexpected exception: " + ex.getClass().getName() + ": " + ex.getMessage(), ex);
}
}
}
}
try {
if (!attributesToRemove.isEmpty()) {
OperationOptions options = new OperationOptionsBuilder().build();
connIdResult = result.createSubresult(ConnectorFacade.class.getName() + ".removeAttributeValues");
connIdResult.addParam("objectClass", objectClassDef);
connIdResult.addParam("uid", uid.getUidValue());
connIdResult.addArbitraryCollectionAsParam("attributes", attributesToRemove);
connIdResult.addArbitraryObjectAsParam("options", options);
connIdResult.addContext("connector", connIdConnectorFacade.getClass());
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Invoking ICF removeAttributeValues(), objectclass={}, uid={}, attributes: {}", new Object[] { objClass, uid, dumpAttributes(attributesToRemove) });
}
InternalMonitor.recordConnectorOperation("removeAttributeValues");
recordIcfOperationStart(reporter, ProvisioningOperation.ICF_UPDATE, objectClassDef, uid);
uid = connIdConnectorFacade.removeAttributeValues(objClass, uid, attributesToRemove, options);
recordIcfOperationEnd(reporter, ProvisioningOperation.ICF_UPDATE, objectClassDef, null, uid);
connIdResult.recordSuccess();
}
} catch (Throwable ex) {
recordIcfOperationEnd(reporter, ProvisioningOperation.ICF_UPDATE, objectClassDef, ex, uid);
String desc = this.getHumanReadableName() + " while removing attribute values from object identified by ICF UID '" + uid.getUidValue() + "'";
Throwable midpointEx = processIcfException(ex, desc, connIdResult);
result.computeStatus("Removing attribute values failed");
// exception
if (midpointEx instanceof ObjectNotFoundException) {
throw (ObjectNotFoundException) midpointEx;
} else if (midpointEx instanceof CommunicationException) {
//in this situation this is not a critical error, becasue we know to handle it..so mute the error and sign it as expected
result.muteError();
connIdResult.muteError();
throw (CommunicationException) midpointEx;
} else if (midpointEx instanceof GenericFrameworkException) {
throw (GenericFrameworkException) midpointEx;
} else if (midpointEx instanceof SchemaException) {
throw (SchemaException) midpointEx;
} else if (midpointEx instanceof ObjectAlreadyExistsException) {
throw (ObjectAlreadyExistsException) midpointEx;
} else if (midpointEx instanceof RuntimeException) {
throw (RuntimeException) midpointEx;
} else if (midpointEx instanceof SecurityViolationException) {
throw (SecurityViolationException) midpointEx;
} else if (midpointEx instanceof Error) {
throw (Error) midpointEx;
} else {
throw new SystemException("Got unexpected exception: " + ex.getClass().getName() + ": " + ex.getMessage(), ex);
}
}
checkAndExecuteAdditionalOperation(reporter, additionalOperations, BeforeAfterType.AFTER, result);
result.computeStatus();
Collection<PropertyModificationOperation> sideEffectChanges = new ArrayList<>();
if (!originalUid.equals(uid.getUidValue())) {
// UID was changed during the operation, this is most likely a
// rename
PropertyDelta<String> uidDelta = createUidDelta(uid, getUidDefinition(objectClassDef, identifiers));
PropertyModificationOperation uidMod = new PropertyModificationOperation(uidDelta);
// TODO what about matchingRuleQName ?
sideEffectChanges.add(uidMod);
replaceUidValue(objectClassDef, identifiers, uid);
}
return AsynchronousOperationReturnValue.wrap(sideEffectChanges, result);
}
use of org.identityconnectors.framework.common.objects.ObjectClass in project midpoint by Evolveum.
the class ConnectorInstanceConnIdImpl method count.
@Override
public int count(ObjectClassComplexTypeDefinition objectClassDefinition, final ObjectQuery query, PagedSearchCapabilityType pagedSearchCapabilityType, StateReporter reporter, OperationResult parentResult) throws CommunicationException, GenericFrameworkException, SchemaException, UnsupportedOperationException {
// Result type for this operation
final OperationResult result = parentResult.createSubresult(ConnectorInstance.class.getName() + ".count");
result.addParam("objectClass", objectClassDefinition);
result.addContext("connector", connectorType);
if (objectClassDefinition == null) {
result.recordFatalError("Object class not defined");
throw new IllegalArgumentException("objectClass not defined");
}
ObjectClass icfObjectClass = connIdNameMapper.objectClassToIcf(objectClassDefinition, getSchemaNamespace(), connectorType, legacySchema);
if (icfObjectClass == null) {
IllegalArgumentException ex = new IllegalArgumentException("Unable to determine object class from QName " + objectClassDefinition + " while attempting to search objects by " + ObjectTypeUtil.toShortString(connectorType));
result.recordFatalError("Unable to determine object class", ex);
throw ex;
}
final boolean useConnectorPaging = pagedSearchCapabilityType != null;
if (!useConnectorPaging) {
throw new UnsupportedOperationException("ConnectorInstanceIcfImpl.count operation is supported only in combination with connector-implemented paging");
}
OperationOptionsBuilder optionsBuilder = new OperationOptionsBuilder();
optionsBuilder.setAttributesToGet(Name.NAME);
optionsBuilder.setPagedResultsOffset(1);
optionsBuilder.setPageSize(1);
if (pagedSearchCapabilityType.getDefaultSortField() != null) {
String orderByIcfName = connIdNameMapper.convertAttributeNameToIcf(pagedSearchCapabilityType.getDefaultSortField(), objectClassDefinition, "(default sorting field)");
boolean isAscending = pagedSearchCapabilityType.getDefaultSortDirection() != OrderDirectionType.DESCENDING;
optionsBuilder.setSortKeys(new SortKey(orderByIcfName, isAscending));
}
OperationOptions options = optionsBuilder.build();
// Connector operation cannot create result for itself, so we need to
// create result for it
OperationResult icfResult = result.createSubresult(ConnectorFacade.class.getName() + ".search");
icfResult.addArbitraryObjectAsParam("objectClass", icfObjectClass);
icfResult.addContext("connector", connIdConnectorFacade.getClass());
int retval;
try {
Filter filter = convertFilterToIcf(query, objectClassDefinition);
final Holder<Integer> fetched = new Holder<>(0);
ResultsHandler icfHandler = new ResultsHandler() {
@Override
public boolean handle(ConnectorObject connectorObject) {
// actually, this should execute at most once
fetched.setValue(fetched.getValue() + 1);
return false;
}
};
InternalMonitor.recordConnectorOperation("search");
recordIcfOperationStart(reporter, ProvisioningOperation.ICF_SEARCH, objectClassDefinition);
SearchResult searchResult = connIdConnectorFacade.search(icfObjectClass, filter, icfHandler, options);
recordIcfOperationEnd(reporter, ProvisioningOperation.ICF_SEARCH, objectClassDefinition);
if (searchResult == null || searchResult.getRemainingPagedResults() == -1) {
throw new UnsupportedOperationException("Connector does not seem to support paged searches or does not provide object count information");
} else {
retval = fetched.getValue() + searchResult.getRemainingPagedResults();
}
icfResult.recordSuccess();
} catch (IntermediateException inex) {
recordIcfOperationEnd(reporter, ProvisioningOperation.ICF_SEARCH, objectClassDefinition, inex);
SchemaException ex = (SchemaException) inex.getCause();
icfResult.recordFatalError(ex);
result.recordFatalError(ex);
throw ex;
} catch (UnsupportedOperationException uoe) {
recordIcfOperationEnd(reporter, ProvisioningOperation.ICF_SEARCH, objectClassDefinition, uoe);
icfResult.recordFatalError(uoe);
result.recordFatalError(uoe);
throw uoe;
} catch (Throwable ex) {
recordIcfOperationEnd(reporter, ProvisioningOperation.ICF_SEARCH, objectClassDefinition, ex);
Throwable midpointEx = processIcfException(ex, this, icfResult);
result.computeStatus();
// exception
if (midpointEx instanceof CommunicationException) {
throw (CommunicationException) midpointEx;
} else if (midpointEx instanceof GenericFrameworkException) {
throw (GenericFrameworkException) midpointEx;
} else if (midpointEx instanceof SchemaException) {
throw (SchemaException) midpointEx;
} else if (midpointEx instanceof RuntimeException) {
throw (RuntimeException) midpointEx;
} else if (midpointEx instanceof Error) {
throw (Error) midpointEx;
} else {
throw new SystemException("Got unexpected exception: " + ex.getClass().getName() + ": " + ex.getMessage(), ex);
}
}
if (result.isUnknown()) {
result.recordSuccess();
}
return retval;
}
use of org.identityconnectors.framework.common.objects.ObjectClass in project midpoint by Evolveum.
the class ConnectorInstanceConnIdImpl method parseResourceSchema.
private void parseResourceSchema(org.identityconnectors.framework.common.objects.Schema icfSchema, List<QName> generateObjectClasses) {
AttributeInfo passwordAttributeInfo = null;
AttributeInfo enableAttributeInfo = null;
AttributeInfo enableDateAttributeInfo = null;
AttributeInfo disableDateAttributeInfo = null;
AttributeInfo lockoutAttributeInfo = null;
AttributeInfo auxiliaryObjectClasseAttributeInfo = null;
// New instance of midPoint schema object
setResourceSchema(new ResourceSchemaImpl(getSchemaNamespace(), prismContext));
if (legacySchema == null) {
legacySchema = detectLegacySchema(icfSchema);
}
LOGGER.trace("Converting resource schema (legacy mode: {})", legacySchema);
Set<ObjectClassInfo> objectClassInfoSet = icfSchema.getObjectClassInfo();
// Let's convert every objectclass in the ICF schema ...
for (ObjectClassInfo objectClassInfo : objectClassInfoSet) {
// "Flat" ICF object class names needs to be mapped to QNames
QName objectClassXsdName = connIdNameMapper.objectClassToQname(new ObjectClass(objectClassInfo.getType()), getSchemaNamespace(), legacySchema);
if (!shouldBeGenerated(generateObjectClasses, objectClassXsdName)) {
LOGGER.trace("Skipping object class {} ({})", objectClassInfo.getType(), objectClassXsdName);
continue;
}
LOGGER.trace("Convering object class {} ({})", objectClassInfo.getType(), objectClassXsdName);
// ResourceObjectDefinition is a midPpoint way how to represent an
// object class.
// The important thing here is the last "type" parameter
// (objectClassXsdName). The rest is more-or-less cosmetics.
ObjectClassComplexTypeDefinition ocDef = ((ResourceSchemaImpl) resourceSchema).createObjectClassDefinition(objectClassXsdName);
// objectclass. So mark it appropriately.
if (ObjectClass.ACCOUNT_NAME.equals(objectClassInfo.getType())) {
((ObjectClassComplexTypeDefinitionImpl) ocDef).setKind(ShadowKindType.ACCOUNT);
((ObjectClassComplexTypeDefinitionImpl) ocDef).setDefaultInAKind(true);
}
ResourceAttributeDefinition<String> uidDefinition = null;
ResourceAttributeDefinition<String> nameDefinition = null;
boolean hasUidDefinition = false;
int displayOrder = ConnectorFactoryConnIdImpl.ATTR_DISPLAY_ORDER_START;
// Let's iterate over all attributes in this object class ...
Set<AttributeInfo> attributeInfoSet = objectClassInfo.getAttributeInfo();
for (AttributeInfo attributeInfo : attributeInfoSet) {
String icfName = attributeInfo.getName();
if (OperationalAttributes.PASSWORD_NAME.equals(icfName)) {
// This attribute will not go into the schema
// instead a "password" capability is used
passwordAttributeInfo = attributeInfo;
// Skip this attribute, capability is sufficient
continue;
}
if (OperationalAttributes.ENABLE_NAME.equals(icfName)) {
enableAttributeInfo = attributeInfo;
// Skip this attribute, capability is sufficient
continue;
}
if (OperationalAttributes.ENABLE_DATE_NAME.equals(icfName)) {
enableDateAttributeInfo = attributeInfo;
// Skip this attribute, capability is sufficient
continue;
}
if (OperationalAttributes.DISABLE_DATE_NAME.equals(icfName)) {
disableDateAttributeInfo = attributeInfo;
// Skip this attribute, capability is sufficient
continue;
}
if (OperationalAttributes.LOCK_OUT_NAME.equals(icfName)) {
lockoutAttributeInfo = attributeInfo;
// Skip this attribute, capability is sufficient
continue;
}
if (PredefinedAttributes.AUXILIARY_OBJECT_CLASS_NAME.equals(icfName)) {
auxiliaryObjectClasseAttributeInfo = attributeInfo;
// Skip this attribute, capability is sufficient
continue;
}
String processedAttributeName = icfName;
if ((Name.NAME.equals(icfName) || Uid.NAME.equals(icfName)) && attributeInfo.getNativeName() != null) {
processedAttributeName = attributeInfo.getNativeName();
}
QName attrXsdName = connIdNameMapper.convertAttributeNameToQName(processedAttributeName, ocDef);
QName attrXsdType = ConnIdUtil.icfTypeToXsdType(attributeInfo.getType(), false);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Attr conversion ICF: {}({}) -> XSD: {}({})", icfName, attributeInfo.getType().getSimpleName(), PrettyPrinter.prettyPrint(attrXsdName), PrettyPrinter.prettyPrint(attrXsdType));
}
// Create ResourceObjectAttributeDefinition, which is midPoint
// way how to express attribute schema.
ResourceAttributeDefinitionImpl attrDef = new ResourceAttributeDefinitionImpl(attrXsdName, attrXsdType, prismContext);
attrDef.setMatchingRuleQName(icfAttributeInfoToMatchingRule(attributeInfo));
if (Name.NAME.equals(icfName)) {
nameDefinition = attrDef;
if (uidDefinition != null && attrXsdName.equals(uidDefinition.getName())) {
attrDef.setDisplayOrder(ConnectorFactoryConnIdImpl.ICFS_UID_DISPLAY_ORDER);
uidDefinition = attrDef;
hasUidDefinition = true;
} else {
if (attributeInfo.getNativeName() == null) {
// Set a better display name for __NAME__. The "name" is s very
// overloaded term, so let's try to make things
// a bit clearer
attrDef.setDisplayName(ConnectorFactoryConnIdImpl.ICFS_NAME_DISPLAY_NAME);
}
attrDef.setDisplayOrder(ConnectorFactoryConnIdImpl.ICFS_NAME_DISPLAY_ORDER);
}
} else if (Uid.NAME.equals(icfName)) {
// UID can be the same as other attribute
ResourceAttributeDefinition existingDefinition = ocDef.findAttributeDefinition(attrXsdName);
if (existingDefinition != null) {
hasUidDefinition = true;
((ResourceAttributeDefinitionImpl) existingDefinition).setDisplayOrder(ConnectorFactoryConnIdImpl.ICFS_UID_DISPLAY_ORDER);
uidDefinition = existingDefinition;
continue;
} else {
uidDefinition = attrDef;
if (attributeInfo.getNativeName() == null) {
attrDef.setDisplayName(ConnectorFactoryConnIdImpl.ICFS_UID_DISPLAY_NAME);
}
attrDef.setDisplayOrder(ConnectorFactoryConnIdImpl.ICFS_UID_DISPLAY_ORDER);
}
} else {
// Check conflict with UID definition
if (uidDefinition != null && attrXsdName.equals(uidDefinition.getName())) {
attrDef.setDisplayOrder(ConnectorFactoryConnIdImpl.ICFS_UID_DISPLAY_ORDER);
uidDefinition = attrDef;
hasUidDefinition = true;
} else {
attrDef.setDisplayOrder(displayOrder);
displayOrder += ConnectorFactoryConnIdImpl.ATTR_DISPLAY_ORDER_INCREMENT;
}
}
attrDef.setNativeAttributeName(attributeInfo.getNativeName());
attrDef.setFrameworkAttributeName(icfName);
// Now we are going to process flags such as optional and
// multi-valued
Set<Flags> flagsSet = attributeInfo.getFlags();
// System.out.println(flagsSet);
attrDef.setMinOccurs(0);
attrDef.setMaxOccurs(1);
boolean canCreate = true;
boolean canUpdate = true;
boolean canRead = true;
for (Flags flags : flagsSet) {
if (flags == Flags.REQUIRED) {
attrDef.setMinOccurs(1);
}
if (flags == Flags.MULTIVALUED) {
attrDef.setMaxOccurs(-1);
}
if (flags == Flags.NOT_CREATABLE) {
canCreate = false;
}
if (flags == Flags.NOT_READABLE) {
canRead = false;
}
if (flags == Flags.NOT_UPDATEABLE) {
canUpdate = false;
}
if (flags == Flags.NOT_RETURNED_BY_DEFAULT) {
attrDef.setReturnedByDefault(false);
}
}
attrDef.setCanAdd(canCreate);
attrDef.setCanModify(canUpdate);
attrDef.setCanRead(canRead);
if (!Uid.NAME.equals(icfName)) {
((ObjectClassComplexTypeDefinitionImpl) ocDef).add(attrDef);
}
}
if (uidDefinition == null) {
// Every object has UID in ICF, therefore add a default definition if no other was specified
uidDefinition = new ResourceAttributeDefinitionImpl<>(SchemaConstants.ICFS_UID, DOMUtil.XSD_STRING, prismContext);
// DO NOT make it mandatory. It must not be present on create hence it cannot be mandatory.
((ResourceAttributeDefinitionImpl) uidDefinition).setMinOccurs(0);
((ResourceAttributeDefinitionImpl) uidDefinition).setMaxOccurs(1);
// Make it read-only
((ResourceAttributeDefinitionImpl) uidDefinition).setReadOnly();
// Set a default display name
((ResourceAttributeDefinitionImpl) uidDefinition).setDisplayName(ConnectorFactoryConnIdImpl.ICFS_UID_DISPLAY_NAME);
((ResourceAttributeDefinitionImpl) uidDefinition).setDisplayOrder(ConnectorFactoryConnIdImpl.ICFS_UID_DISPLAY_ORDER);
// Uid is a primary identifier of every object (this is the ICF way)
}
if (!hasUidDefinition) {
((ObjectClassComplexTypeDefinitionImpl) ocDef).add(uidDefinition);
}
((ObjectClassComplexTypeDefinitionImpl) ocDef).addPrimaryIdentifier(uidDefinition);
if (uidDefinition != nameDefinition) {
((ObjectClassComplexTypeDefinitionImpl) ocDef).addSecondaryIdentifier(nameDefinition);
}
// Add schema annotations
((ObjectClassComplexTypeDefinitionImpl) ocDef).setNativeObjectClass(objectClassInfo.getType());
((ObjectClassComplexTypeDefinitionImpl) ocDef).setDisplayNameAttribute(nameDefinition.getName());
((ObjectClassComplexTypeDefinitionImpl) ocDef).setNamingAttribute(nameDefinition.getName());
((ObjectClassComplexTypeDefinitionImpl) ocDef).setAuxiliary(objectClassInfo.isAuxiliary());
}
// This is the default for all resources.
// (Currently there is no way how to obtain it from the connector.)
// It can be disabled manually.
AddRemoveAttributeValuesCapabilityType addRemove = new AddRemoveAttributeValuesCapabilityType();
capabilities.add(CAPABILITY_OBJECT_FACTORY.createAddRemoveAttributeValues(addRemove));
ActivationCapabilityType capAct = null;
if (enableAttributeInfo != null) {
if (capAct == null) {
capAct = new ActivationCapabilityType();
}
ActivationStatusCapabilityType capActStatus = new ActivationStatusCapabilityType();
capAct.setStatus(capActStatus);
if (!enableAttributeInfo.isReturnedByDefault()) {
capActStatus.setReturnedByDefault(false);
}
}
if (enableDateAttributeInfo != null) {
if (capAct == null) {
capAct = new ActivationCapabilityType();
}
ActivationValidityCapabilityType capValidFrom = new ActivationValidityCapabilityType();
capAct.setValidFrom(capValidFrom);
if (!enableDateAttributeInfo.isReturnedByDefault()) {
capValidFrom.setReturnedByDefault(false);
}
}
if (disableDateAttributeInfo != null) {
if (capAct == null) {
capAct = new ActivationCapabilityType();
}
ActivationValidityCapabilityType capValidTo = new ActivationValidityCapabilityType();
capAct.setValidTo(capValidTo);
if (!disableDateAttributeInfo.isReturnedByDefault()) {
capValidTo.setReturnedByDefault(false);
}
}
if (lockoutAttributeInfo != null) {
if (capAct == null) {
capAct = new ActivationCapabilityType();
}
ActivationLockoutStatusCapabilityType capActStatus = new ActivationLockoutStatusCapabilityType();
capAct.setLockoutStatus(capActStatus);
if (!lockoutAttributeInfo.isReturnedByDefault()) {
capActStatus.setReturnedByDefault(false);
}
}
if (capAct != null) {
capabilities.add(CAPABILITY_OBJECT_FACTORY.createActivation(capAct));
}
if (passwordAttributeInfo != null) {
CredentialsCapabilityType capCred = new CredentialsCapabilityType();
PasswordCapabilityType capPass = new PasswordCapabilityType();
if (!passwordAttributeInfo.isReturnedByDefault()) {
capPass.setReturnedByDefault(false);
}
if (passwordAttributeInfo.isReadable()) {
capPass.setReadable(true);
}
capCred.setPassword(capPass);
capabilities.add(CAPABILITY_OBJECT_FACTORY.createCredentials(capCred));
}
if (auxiliaryObjectClasseAttributeInfo != null) {
AuxiliaryObjectClassesCapabilityType capAux = new AuxiliaryObjectClassesCapabilityType();
capabilities.add(CAPABILITY_OBJECT_FACTORY.createAuxiliaryObjectClasses(capAux));
}
boolean canPageSize = false;
boolean canPageOffset = false;
boolean canSort = false;
for (OperationOptionInfo searchOption : icfSchema.getSupportedOptionsByOperation(SearchApiOp.class)) {
switch(searchOption.getName()) {
case OperationOptions.OP_PAGE_SIZE:
canPageSize = true;
break;
case OperationOptions.OP_PAGED_RESULTS_OFFSET:
canPageOffset = true;
break;
case OperationOptions.OP_SORT_KEYS:
canSort = true;
break;
case OperationOptions.OP_RETURN_DEFAULT_ATTRIBUTES:
supportsReturnDefaultAttributes = true;
break;
}
}
if (canPageSize || canPageOffset || canSort) {
PagedSearchCapabilityType capPage = new PagedSearchCapabilityType();
capabilities.add(CAPABILITY_OBJECT_FACTORY.createPagedSearch(capPage));
}
}
use of org.identityconnectors.framework.common.objects.ObjectClass in project midpoint by Evolveum.
the class ConnectorInstanceConnIdImpl method fetchChanges.
@Override
public List<Change> fetchChanges(ObjectClassComplexTypeDefinition objectClass, PrismProperty<?> lastToken, AttributesToReturn attrsToReturn, StateReporter reporter, OperationResult parentResult) throws CommunicationException, GenericFrameworkException, SchemaException, ConfigurationException {
OperationResult result = parentResult.createSubresult(ConnectorInstance.class.getName() + ".fetchChanges");
result.addContext("objectClass", objectClass);
result.addParam("lastToken", lastToken);
// create sync token from the property last token
SyncToken syncToken = null;
try {
syncToken = getSyncToken(lastToken);
LOGGER.trace("Sync token created from the property last token: {}", syncToken == null ? null : syncToken.getValue());
} catch (SchemaException ex) {
result.recordFatalError(ex.getMessage(), ex);
throw new SchemaException(ex.getMessage(), ex);
}
final List<SyncDelta> syncDeltas = new ArrayList<SyncDelta>();
// get icf object class
ObjectClass icfObjectClass;
if (objectClass == null) {
icfObjectClass = ObjectClass.ALL;
} else {
icfObjectClass = connIdNameMapper.objectClassToIcf(objectClass, getSchemaNamespace(), connectorType, legacySchema);
}
OperationOptionsBuilder optionsBuilder = new OperationOptionsBuilder();
if (objectClass != null) {
convertToIcfAttrsToGet(objectClass, attrsToReturn, optionsBuilder);
}
OperationOptions options = optionsBuilder.build();
SyncResultsHandler syncHandler = new SyncResultsHandler() {
@Override
public boolean handle(SyncDelta delta) {
LOGGER.trace("Detected sync delta: {}", delta);
return syncDeltas.add(delta);
}
};
OperationResult connIdResult = result.createSubresult(ConnectorFacade.class.getName() + ".sync");
connIdResult.addContext("connector", connIdConnectorFacade.getClass());
connIdResult.addArbitraryObjectAsParam("connIdObjectClass", icfObjectClass);
connIdResult.addArbitraryObjectAsParam("syncToken", syncToken);
connIdResult.addArbitraryObjectAsParam("syncHandler", syncHandler);
SyncToken lastReceivedToken;
try {
InternalMonitor.recordConnectorOperation("sync");
recordIcfOperationStart(reporter, ProvisioningOperation.ICF_SYNC, objectClass);
lastReceivedToken = connIdConnectorFacade.sync(icfObjectClass, syncToken, syncHandler, options);
recordIcfOperationEnd(reporter, ProvisioningOperation.ICF_SYNC, objectClass);
connIdResult.recordSuccess();
connIdResult.addReturn(OperationResult.RETURN_COUNT, syncDeltas.size());
} catch (Throwable ex) {
recordIcfOperationEnd(reporter, ProvisioningOperation.ICF_SYNC, objectClass, ex);
Throwable midpointEx = processIcfException(ex, this, connIdResult);
result.computeStatus();
// exception
if (midpointEx instanceof CommunicationException) {
throw (CommunicationException) midpointEx;
} else if (midpointEx instanceof GenericFrameworkException) {
throw (GenericFrameworkException) midpointEx;
} else if (midpointEx instanceof SchemaException) {
throw (SchemaException) midpointEx;
} else if (midpointEx instanceof RuntimeException) {
throw (RuntimeException) midpointEx;
} else if (midpointEx instanceof Error) {
throw (Error) midpointEx;
} else {
throw new SystemException("Got unexpected exception: " + ex.getClass().getName() + ": " + ex.getMessage(), ex);
}
}
// convert changes from icf to midpoint Change
List<Change> changeList;
try {
changeList = getChangesFromSyncDeltas(icfObjectClass, syncDeltas, resourceSchema, result);
} catch (SchemaException ex) {
result.recordFatalError(ex.getMessage(), ex);
throw new SchemaException(ex.getMessage(), ex);
}
if (lastReceivedToken != null) {
Change lastChange = new Change((ObjectDelta) null, getToken(lastReceivedToken));
LOGGER.trace("Adding last change: {}", lastChange);
changeList.add(lastChange);
}
result.recordSuccess();
result.addReturn(OperationResult.RETURN_COUNT, changeList == null ? 0 : changeList.size());
return changeList;
}
Aggregations