use of com.evolveum.midpoint.schema.reporting.ConnIdOperation in project midpoint by Evolveum.
the class ConnectorInstanceConnIdImpl method executeScriptIcf.
private Object executeScriptIcf(UcfExecutionContext reporter, ExecuteProvisioningScriptOperation scriptOperation, OperationResult parentResult) throws CommunicationException, GenericFrameworkException {
String icfOpName;
if (scriptOperation.isConnectorHost()) {
icfOpName = "runScriptOnConnector";
} else if (scriptOperation.isResourceHost()) {
icfOpName = "runScriptOnResource";
} else {
throw new IllegalArgumentException("Where to execute the script?");
}
// convert execute script operation to the script context required from
// the connector
ScriptContext scriptContext = convertToScriptContext(scriptOperation);
OperationResult icfResult = parentResult.createSubresult(ConnectorFacade.class.getName() + "." + icfOpName);
icfResult.addContext("connector", connIdConnectorFacade.getClass());
ConnIdOperation operation = recordIcfOperationStart(reporter, ProvisioningOperation.ICF_SCRIPT, null);
Object output = null;
try {
LOGGER.trace("Running script ({}): {}", icfOpName, operation);
if (scriptOperation.isConnectorHost()) {
InternalMonitor.recordConnectorOperation("runScriptOnConnector");
output = connIdConnectorFacade.runScriptOnConnector(scriptContext, new OperationOptionsBuilder().build());
} else if (scriptOperation.isResourceHost()) {
InternalMonitor.recordConnectorOperation("runScriptOnResource");
output = connIdConnectorFacade.runScriptOnResource(scriptContext, new OperationOptionsBuilder().build());
}
recordIcfOperationEnd(reporter, operation, null);
icfResult.recordSuccess();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Finished running script ({}), script result: {}", icfOpName, PrettyPrinter.prettyPrint(output));
}
} catch (Throwable ex) {
recordIcfOperationEnd(reporter, operation, ex);
LOGGER.debug("Finished running script ({}), ERROR: {}", icfOpName, ex.getMessage());
Throwable midpointEx = processConnIdException(ex, this, icfResult);
CriticalityType criticality = scriptOperation.getCriticality();
if (criticality == null || criticality == CriticalityType.FATAL) {
parentResult.computeStatus();
// exception
if (midpointEx instanceof CommunicationException) {
throw (CommunicationException) midpointEx;
} else if (midpointEx instanceof GenericFrameworkException) {
throw (GenericFrameworkException) midpointEx;
} else if (midpointEx instanceof SchemaException) {
// Schema exception during delete? It must be a missing UID
throw new IllegalArgumentException(midpointEx.getMessage(), 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);
}
} else if (criticality == CriticalityType.PARTIAL) {
icfResult.setStatus(OperationResultStatus.PARTIAL_ERROR);
parentResult.computeStatus();
}
}
return output;
}
use of com.evolveum.midpoint.schema.reporting.ConnIdOperation in project midpoint by Evolveum.
the class ConnectorInstanceConnIdImpl method deleteObject.
@Override
public AsynchronousOperationResult deleteObject(ResourceObjectDefinition objectDefinition, PrismObject<ShadowType> shadow, Collection<? extends ResourceAttribute<?>> identifiers, UcfExecutionContext ctx, OperationResult parentResult) throws ObjectNotFoundException, CommunicationException, GenericFrameworkException, SchemaException {
Validate.notNull(objectDefinition, "No objectclass");
OperationResult result = parentResult.createSubresult(ConnectorInstance.class.getName() + ".deleteObject");
result.addArbitraryObjectCollectionAsParam("identifiers", identifiers);
ObjectClass objClass = objectClassToConnId(objectDefinition);
Uid uid;
try {
uid = getUid(objectDefinition, identifiers);
} catch (SchemaException e) {
result.recordFatalError(e);
throw e;
}
OperationResult icfResult = result.createSubresult(ConnectorFacade.class.getName() + ".delete");
icfResult.addArbitraryObjectAsParam("uid", uid);
icfResult.addArbitraryObjectAsParam("objectClass", objClass);
icfResult.addContext("connector", connIdConnectorFacade.getClass());
InternalMonitor.recordConnectorOperation("delete");
InternalMonitor.recordConnectorModification("delete");
ConnIdOperation operation = recordIcfOperationStart(ctx, ProvisioningOperation.ICF_DELETE, objectDefinition, uid);
LOGGER.trace("Invoking ConnId delete operation: {}", operation);
try {
connIdConnectorFacade.delete(objClass, uid, new OperationOptionsBuilder().build());
recordIcfOperationEnd(ctx, operation, null);
icfResult.recordSuccess();
} catch (Throwable ex) {
recordIcfOperationEnd(ctx, operation, ex);
String desc = this.getHumanReadableName() + " while deleting object identified by ConnId UID '" + uid.getUidValue() + "'";
Throwable midpointEx = processConnIdException(ex, desc, icfResult);
result.computeStatus("Removing attribute values failed");
// exception
if (midpointEx instanceof ObjectNotFoundException) {
throw (ObjectNotFoundException) midpointEx;
} else if (midpointEx instanceof CommunicationException) {
throw (CommunicationException) midpointEx;
} else if (midpointEx instanceof GenericFrameworkException) {
throw (GenericFrameworkException) midpointEx;
} else if (midpointEx instanceof SchemaException) {
// Schema exception during delete? It must be a missing UID
throw new IllegalArgumentException(midpointEx.getMessage(), 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);
}
}
result.computeStatus();
return AsynchronousOperationResult.wrap(result);
}
use of com.evolveum.midpoint.schema.reporting.ConnIdOperation in project midpoint by Evolveum.
the class ConnectorInstanceConnIdImpl method addObject.
@Override
public AsynchronousOperationReturnValue<Collection<ResourceAttribute<?>>> addObject(PrismObject<? extends ShadowType> shadow, UcfExecutionContext ctx, OperationResult parentResult) throws CommunicationException, GenericFrameworkException, SchemaException, ObjectAlreadyExistsException, ConfigurationException, SecurityViolationException, PolicyViolationException {
validateShadow(shadow, "add", false);
ShadowType shadowType = shadow.asObjectable();
ResourceAttributeContainer attributesContainer = ShadowUtil.getAttributesContainer(shadow);
OperationResult result = parentResult.createSubresult(ConnectorInstance.class.getName() + ".addObject");
result.addParam("resourceObject", shadow);
ResourceObjectDefinition ocDef;
ResourceAttributeContainerDefinition attrContDef = attributesContainer.getDefinition();
if (attrContDef != null) {
ocDef = attrContDef.getComplexTypeDefinition();
} else {
ocDef = rawResourceSchema.findObjectClassDefinition(shadow.asObjectable().getObjectClass());
if (ocDef == null) {
throw new SchemaException("Unknown object class " + shadow.asObjectable().getObjectClass());
}
}
// getting icf object class from resource object class
ObjectClass icfObjectClass = connIdNameMapper.objectClassToConnId(shadow, connectorType, BooleanUtils.isNotFalse(legacySchema));
if (icfObjectClass == null) {
result.recordFatalError("Couldn't get icf object class from " + shadow);
throw new IllegalArgumentException("Couldn't get icf object class from " + shadow);
}
// setting ifc attributes from resource object attributes
Set<Attribute> attributes;
try {
LOGGER.trace("midPoint object before conversion:\n{}", attributesContainer.debugDumpLazily());
attributes = connIdConvertor.convertFromResourceObjectToConnIdAttributes(attributesContainer, ocDef);
if (shadowType.getCredentials() != null && shadowType.getCredentials().getPassword() != null) {
PasswordType password = shadowType.getCredentials().getPassword();
ProtectedStringType protectedString = password.getValue();
GuardedString guardedPassword = ConnIdUtil.toGuardedString(protectedString, "new password", protector);
if (guardedPassword != null) {
attributes.add(AttributeBuilder.build(OperationalAttributes.PASSWORD_NAME, guardedPassword));
}
}
if (ActivationUtil.hasAdministrativeActivation(shadowType)) {
attributes.add(AttributeBuilder.build(OperationalAttributes.ENABLE_NAME, ActivationUtil.isAdministrativeEnabled(shadowType)));
}
if (ActivationUtil.hasValidFrom(shadowType)) {
attributes.add(AttributeBuilder.build(OperationalAttributes.ENABLE_DATE_NAME, XmlTypeConverter.toMillis(shadowType.getActivation().getValidFrom())));
}
if (ActivationUtil.hasValidTo(shadowType)) {
attributes.add(AttributeBuilder.build(OperationalAttributes.DISABLE_DATE_NAME, XmlTypeConverter.toMillis(shadowType.getActivation().getValidTo())));
}
if (ActivationUtil.hasLockoutStatus(shadowType)) {
attributes.add(AttributeBuilder.build(OperationalAttributes.LOCK_OUT_NAME, ActivationUtil.isLockedOut(shadowType)));
}
LOGGER.trace("ConnId attributes after conversion:\n{}", lazy(() -> ConnIdUtil.dump(attributes)));
} catch (SchemaException | RuntimeException 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);
}
List<String> icfAuxiliaryObjectClasses = new ArrayList<>();
for (QName auxiliaryObjectClass : shadowType.getAuxiliaryObjectClass()) {
icfAuxiliaryObjectClasses.add(connIdNameMapper.objectClassToConnId(auxiliaryObjectClass, connectorType, false).getObjectClassValue());
}
if (!icfAuxiliaryObjectClasses.isEmpty()) {
AttributeBuilder ab = new AttributeBuilder();
ab.setName(PredefinedAttributes.AUXILIARY_OBJECT_CLASS_NAME);
ab.addValue(icfAuxiliaryObjectClasses);
attributes.add(ab.build());
}
OperationOptionsBuilder operationOptionsBuilder = new OperationOptionsBuilder();
OperationOptions options = operationOptionsBuilder.build();
OperationResult connIdResult = result.createSubresult(ConnectorFacade.class.getName() + ".create");
connIdResult.addArbitraryObjectAsParam("objectClass", icfObjectClass);
connIdResult.addArbitraryObjectCollectionAsParam("auxiliaryObjectClasses", icfAuxiliaryObjectClasses);
connIdResult.addArbitraryObjectCollectionAsParam("attributes", attributes);
connIdResult.addArbitraryObjectAsParam("options", options);
connIdResult.addContext("connector", connIdConnectorFacade.getClass());
// CALL THE ConnId FRAMEWORK
InternalMonitor.recordConnectorOperation("create");
InternalMonitor.recordConnectorModification("create");
ConnIdOperation operation = recordIcfOperationStart(ctx, ProvisioningOperation.ICF_CREATE, ocDef, null);
Uid uid;
try {
LOGGER.trace("Calling ConnId create for {}", operation);
uid = connIdConnectorFacade.create(icfObjectClass, attributes, options);
if (operation != null && uid != null) {
operation.setUid(uid.getUidValue());
}
recordIcfOperationEnd(ctx, operation, null);
} catch (Throwable ex) {
recordIcfOperationEnd(ctx, operation, ex);
Throwable midpointEx = processConnIdException(ex, this, connIdResult);
result.computeStatus("Add object failed");
// exception
if (midpointEx instanceof ObjectAlreadyExistsException) {
throw (ObjectAlreadyExistsException) midpointEx;
} else if (midpointEx instanceof CommunicationException) {
// result.muteError();
throw (CommunicationException) midpointEx;
} else if (midpointEx instanceof GenericFrameworkException) {
throw (GenericFrameworkException) midpointEx;
} else if (midpointEx instanceof SchemaException) {
throw (SchemaException) midpointEx;
} else if (midpointEx instanceof ConfigurationException) {
throw (ConfigurationException) midpointEx;
} else if (midpointEx instanceof SecurityViolationException) {
throw (SecurityViolationException) midpointEx;
} else if (midpointEx instanceof PolicyViolationException) {
throw (PolicyViolationException) 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 (uid == null || uid.getUidValue() == null || uid.getUidValue().isEmpty()) {
connIdResult.recordFatalError("ConnId did not returned UID after create");
result.computeStatus("Add object failed");
throw new GenericFrameworkException("ConnId did not returned UID after create");
}
Collection<ResourceAttribute<?>> identifiers = ConnIdUtil.convertToIdentifiers(uid, attributesContainer.getDefinition().getComplexTypeDefinition(), rawResourceSchema);
for (ResourceAttribute<?> identifier : identifiers) {
attributesContainer.getValue().addReplaceExisting(identifier);
}
connIdResult.recordSuccess();
result.computeStatus();
return AsynchronousOperationReturnValue.wrap(attributesContainer.getAttributes(), result);
}
use of com.evolveum.midpoint.schema.reporting.ConnIdOperation in project midpoint by Evolveum.
the class ConnectorInstanceConnIdImpl method fetchChanges.
@Override
public UcfFetchChangesResult fetchChanges(ResourceObjectDefinition objectDefinition, UcfSyncToken initialTokenValue, AttributesToReturn attrsToReturn, Integer maxChanges, UcfExecutionContext ctx, @NotNull UcfLiveSyncChangeListener changeListener, OperationResult parentResult) throws CommunicationException, GenericFrameworkException, SchemaException {
OperationResult result = parentResult.subresult(OP_FETCH_CHANGES).addArbitraryObjectAsContext("objectClass", objectDefinition).addArbitraryObjectAsParam("initialToken", initialTokenValue).build();
try {
SyncToken initialToken = TokenUtil.toConnId(initialTokenValue);
LOGGER.trace("Initial token: {}", initialToken == null ? null : initialToken.getValue());
ResourceObjectClassDefinition objectClassDefinition = objectDefinition != null ? objectDefinition.getObjectClassDefinition() : null;
// get icf object class
ObjectClass requestConnIdObjectClass;
if (objectClassDefinition == null) {
requestConnIdObjectClass = ObjectClass.ALL;
} else {
requestConnIdObjectClass = objectClassToConnId(objectClassDefinition);
}
OperationOptionsBuilder optionsBuilder = new OperationOptionsBuilder();
if (objectDefinition != null) {
convertToIcfAttrsToGet(objectDefinition, attrsToReturn, optionsBuilder);
}
OperationOptions options = optionsBuilder.build();
AtomicInteger deltasProcessed = new AtomicInteger(0);
Thread callerThread = Thread.currentThread();
SyncDeltaConverter changeConverter = new SyncDeltaConverter(this, objectDefinition);
AtomicBoolean allChangesFetched = new AtomicBoolean(true);
UcfFetchChangesResult fetchChangesResult;
OperationResult connIdResult = result.subresult(ConnectorFacade.class.getName() + ".sync").addContext("connector", connIdConnectorFacade.getClass()).addArbitraryObjectAsParam("objectClass", requestConnIdObjectClass).addArbitraryObjectAsParam("initialToken", initialToken).build();
try {
InternalMonitor.recordConnectorOperation("sync");
ConnIdOperation operation = recordIcfOperationStart(ctx, ProvisioningOperation.ICF_SYNC, objectDefinition);
/*
* We assume that the only way how changes are _not_ fetched is that we explicitly tell ConnId to stop
* fetching them by returning 'false' from the handler.handle() method. (Or an exception occurs in the sync()
* method.)
*
* In other words, we assume that if we tell ConnId to continue feeding changes to us, we are sure that on
* successful exit from sync() method all changes were processed.
*/
SyncResultsHandler syncHandler = syncDelta -> {
Thread handlingThread = Thread.currentThread();
if (!handlingThread.equals(callerThread)) {
LOGGER.warn("Live Sync changes are being processed in a thread {} that is different from the invoking one ({}). " + "This can cause issues e.g. with operational statistics reporting.", handlingThread, callerThread);
}
recordIcfOperationSuspend(ctx, operation);
LOGGER.trace("Received sync delta: {}", syncDelta);
OperationResult handleResult;
// But - just for sure - let us create subresults in a safe way.
synchronized (connIdResult) {
handleResult = connIdResult.subresult(OP_FETCH_CHANGES + ".handle").addArbitraryObjectAsParam("uid", syncDelta.getUid()).setMinor().build();
}
UcfLiveSyncChange change = null;
try {
// Here we again assume we are called in a single thread, and that changes received here are in
// the correct order - i.e. in the order in which they are to be processed.
int sequentialNumber = deltasProcessed.incrementAndGet();
change = changeConverter.createChange(sequentialNumber, syncDelta, handleResult);
// The following should not throw any exceptions
boolean canContinue = changeListener.onChange(change, handleResult);
boolean doContinue = canContinue && canRun(ctx) && (maxChanges == null || maxChanges == 0 || sequentialNumber < maxChanges);
if (!doContinue) {
allChangesFetched.set(false);
}
return doContinue;
} catch (RuntimeException e) {
handleResult.recordFatalError(e);
// any exception here is not expected
LoggingUtils.logUnexpectedException(LOGGER, "Got unexpected exception while handling live sync " + "change, stopping the processing. Sync delta: {}, UCF change: {}", e, syncDelta, change);
return false;
} finally {
// Asynchronously processed changes (if used) have their own, separate, operation results
// that are tied to the lightweight asynchronous task handlers in ChangeProcessingCoordinator.
//
// So we can safely compute/cleanup/summarize results here.
handleResult.computeStatusIfUnknown();
handleResult.cleanupResult();
connIdResult.summarize(true);
recordIcfOperationResume(ctx, operation);
}
};
LOGGER.trace("Invoking ConnId sync operation: {}", operation);
SyncToken finalToken;
try {
finalToken = connIdConnectorFacade.sync(requestConnIdObjectClass, initialToken, syncHandler, options);
// Note that finalToken value is not quite reliable. The SyncApiOp documentation is not clear on its semantics;
// it is only from SyncTokenResultsHandler (SPI) documentation and SyncImpl class that we know this value is
// non-null when all changes were fetched. And some of the connectors return null even then.
LOGGER.trace("connector sync method returned: {}", finalToken);
connIdResult.computeStatus();
connIdResult.cleanupResult();
connIdResult.addReturn(OperationResult.RETURN_COUNT, deltasProcessed.get());
recordIcfOperationEnd(ctx, operation, null);
} catch (Throwable ex) {
recordIcfOperationEnd(ctx, operation, ex);
Throwable midpointEx = processConnIdException(ex, this, connIdResult);
connIdResult.computeStatusIfUnknown();
connIdResult.cleanupResult();
result.computeStatus();
// Do some kind of acrobatics to do proper throwing of checked 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 (!canRun(ctx)) {
result.recordStatus(OperationResultStatus.SUCCESS, "Interrupted by task suspension");
}
if (allChangesFetched.get()) {
// We might consider finalToken value here. I.e. it it's non null, we could declare all changes to be fetched.
// But as mentioned above, this is not supported explicitly in SyncApiOp. So let's be a bit conservative.
LOGGER.trace("All changes were fetched; with finalToken = {}", finalToken);
fetchChangesResult = new UcfFetchChangesResult(true, TokenUtil.toUcf(finalToken));
} else {
fetchChangesResult = new UcfFetchChangesResult(false, null);
}
} catch (Throwable t) {
connIdResult.recordFatalError(t);
throw t;
} finally {
connIdResult.computeStatusIfUnknown();
}
result.recordSuccess();
result.addReturn(OperationResult.RETURN_COUNT, deltasProcessed.get());
return fetchChangesResult;
} catch (Throwable t) {
result.recordFatalError(t);
throw t;
} finally {
result.computeStatusIfUnknown();
}
}
use of com.evolveum.midpoint.schema.reporting.ConnIdOperation in project midpoint by Evolveum.
the class ConnectorInstanceConnIdImpl method fetchCurrentToken.
@Override
public UcfSyncToken fetchCurrentToken(ResourceObjectDefinition objectDefinition, UcfExecutionContext ctx, OperationResult parentResult) throws CommunicationException, GenericFrameworkException {
OperationResult result = parentResult.createSubresult(ConnectorInstance.class.getName() + ".fetchCurrentToken");
result.addArbitraryObjectAsParam("objectClass", objectDefinition);
ObjectClass icfObjectClass;
if (objectDefinition == null) {
icfObjectClass = ObjectClass.ALL;
} else {
icfObjectClass = objectClassToConnId(objectDefinition);
}
OperationResult icfResult = result.createSubresult(ConnectorFacade.class.getName() + ".sync");
icfResult.addContext("connector", connIdConnectorFacade.getClass());
icfResult.addArbitraryObjectAsParam("icfObjectClass", icfObjectClass);
SyncToken syncToken;
InternalMonitor.recordConnectorOperation("getLatestSyncToken");
ConnIdOperation operation = recordIcfOperationStart(ctx, ProvisioningOperation.ICF_GET_LATEST_SYNC_TOKEN, objectDefinition);
LOGGER.trace("Invoking ConnId getLatestSyncToken operation: {}", operation);
try {
syncToken = connIdConnectorFacade.getLatestSyncToken(icfObjectClass);
recordIcfOperationEnd(ctx, operation, null);
icfResult.recordSuccess();
icfResult.addReturn("syncToken", syncToken == null ? null : String.valueOf(syncToken.getValue()));
} catch (Throwable ex) {
recordIcfOperationEnd(ctx, operation, ex);
Throwable midpointEx = processConnIdException(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.recordSuccess();
return TokenUtil.toUcf(syncToken);
} else {
result.recordWarning("Resource has not provided a current sync token");
return null;
}
}
Aggregations