use of eu.bcvsolutions.idm.core.api.exception.ResultCodeException in project CzechIdMng by bcvsolutions.
the class DefaultImportManager method executeImportForType.
/**
* Ensures add new and update existed DTOs by given batch.
*
* @param descriptor
* @param context
*/
private void executeImportForType(ExportDescriptorDto descriptor, ImportContext context) {
Class<? extends BaseDto> dtoClass = descriptor.getDtoClass();
Path dtoTypePath = Paths.get(context.getTempDirectory().toString(), dtoClass.getSimpleName());
try {
List<BaseDto> dtos;
try (Stream<Path> paths = Files.walk(dtoTypePath)) {
dtos = //
paths.filter(//
Files::isRegularFile).map(path -> {
BaseDto dto = convertFileToDto(path.toFile(), dtoClass, context);
Assert.notNull(dto, "DTO cannot be null after conversion from the batch!");
return dto;
}).collect(Collectors.toList());
}
if (dtos.isEmpty()) {
return;
}
// Sorts all DTOs for this type (maybe it is tree).
dtos = sortsDTOs(dtoClass, dtos);
int i = 0;
for (BaseDto dto : dtos) {
// Flush Hibernate in batch - performance improving
if (i % 20 == 0 && i > 0) {
// Call hard hibernate session flush and clear
if (getHibernateSession().isOpen()) {
getHibernateSession().flush();
getHibernateSession().clear();
}
}
i++;
// Increase counter and update state of import LRT.
context.getImportTaskExecutor().increaseCounter();
context.getImportTaskExecutor().updateState();
BaseDto parentDto = getParentDtoFromBatch(dto, context);
if (parentDto == null) {
parentDto = dto;
}
BaseDto originalDto = dto;
try {
dto = makeAdvancedPairing(dto, context, dtoClass);
if (dto == null) {
// If DTO after advanced pairing is null, then was not found and is optional ->
// skip.
IdmImportLogDto dtoLog = new IdmImportLogDto(context.getBatch(), originalDto, RequestOperationType.ADD, (UUID) parentDto.getId());
ResultModel resultModel = new DefaultResultModel(CoreResultCode.IMPORT_DTO_SKIPPED, ImmutableMap.of("dto", originalDto.toString()));
dtoLog.setResult(new OperationResultDto.Builder(OperationState.CANCELED).setModel(resultModel).build());
importLogService.saveDistinct(dtoLog);
continue;
}
} catch (ResultCodeException ex) {
if (context.isDryRun() && ex.getError() != null && ex.getError().getError() != null && CoreResultCode.IMPORT_ADVANCED_PARING_FAILED_NOT_FOUND.name().equals(ex.getError().getError().getStatusEnum())) {
// Not found DTO we will mark as skipped in dry run mode.
IdmImportLogDto dtoLog = new IdmImportLogDto(context.getBatch(), originalDto, RequestOperationType.ADD, (UUID) parentDto.getId());
dtoLog.setResult(new OperationResultDto.Builder(OperationState.EXCEPTION).setException(ex).build());
importLogService.saveDistinct(dtoLog);
continue;
} else if (ex.getError() != null && ex.getError().getError() != null && CoreResultCode.IMPORT_ADVANCED_PARING_NOT_FOUND_OPTIONAL.name().equals(ex.getError().getError().getStatusEnum())) {
// Not found DTO, but optional, we will mark as skipped.
IdmImportLogDto dtoLog = new IdmImportLogDto(context.getBatch(), originalDto, RequestOperationType.ADD, (UUID) parentDto.getId());
dtoLog.setResult(new OperationResultDto.Builder(OperationState.CANCELED).setException(ex).build());
importLogService.saveDistinct(dtoLog);
continue;
}
throw ex;
}
Class<? extends BaseDto> serviceDtoClass = dtoClass;
if (dto instanceof IdmFormInstanceDto) {
// Form instance is very special here (doesn't have entity in DB).
IdmFormInstanceDto formInstance = (IdmFormInstanceDto) dto;
IdmFormDefinitionDto definition = formInstance.getFormDefinition();
Assert.notNull(definition, "Definition cannot be null for import!");
CoreEvent<IdmFormInstanceDto> event = new CoreEvent<>(CoreEventType.UPDATE, formInstance);
// Check if owner exist (UPDATE/ADD)
@SuppressWarnings("unchecked") Class<? extends BaseDto> ownerType = (Class<? extends BaseDto>) ((IdmFormInstanceDto) dto).getOwnerType();
UUID ownerId = UUID.fromString((String) ((IdmFormInstanceDto) dto).getOwnerId());
BaseDto ownerDto = this.getDtoService(ownerType).get(ownerId);
IdmImportLogDto dtoLog = new IdmImportLogDto(context.getBatch(), dto, ownerDto != null ? RequestOperationType.UPDATE : RequestOperationType.ADD, ownerId);
if (!context.isDryRun()) {
formService.publish(event);
dtoLog.setResult(new OperationResultDto(OperationState.EXECUTED));
} else {
dtoLog.setResult(new OperationResultDto.Builder(OperationState.NOT_EXECUTED).setModel(//
new DefaultResultModel(CoreResultCode.IMPORT_EXECUTED_AS_DRYRUN)).build());
}
importLogService.saveDistinct(dtoLog);
continue;
}
if (dto.getClass().isAnnotationPresent(Inheritable.class)) {
serviceDtoClass = dto.getClass().getAnnotation(Inheritable.class).dtoService();
}
ReadWriteDtoService<BaseDto, ?> dtoService = getDtoService(serviceDtoClass);
BaseDto currentDto = dtoService.get(dto.getId());
if (currentDto != null) {
// DTO with same ID already exists -> update.
IdmImportLogDto dtoLog = new IdmImportLogDto(context.getBatch(), dto, RequestOperationType.UPDATE, (UUID) parentDto.getId());
// Resolve excluded fields
dto = this.excludeFields(dto, currentDto, context);
if (!context.isDryRun()) {
dtoService.save(dto);
dtoLog.setResult(new OperationResultDto(OperationState.EXECUTED));
} else {
dtoLog.setResult(new OperationResultDto.Builder(OperationState.NOT_EXECUTED).setModel(//
new DefaultResultModel(CoreResultCode.IMPORT_EXECUTED_AS_DRYRUN)).build());
}
importLogService.saveDistinct(dtoLog);
continue;
}
if (dto instanceof Codeable) {
// We try to find exists DTO by code.
currentDto = lookupService.lookupDto(serviceDtoClass, ((Codeable) dto).getCode());
}
// Find target DTO by example source DTO (typically by more then one filter field).
currentDto = findByExample(dto, null, context);
if (dto instanceof IdmFormDefinitionDto) {
IdmFormDefinitionDto definition = (IdmFormDefinitionDto) dto;
// We try to find exists definition by code and type (IdmFormDefinitionDto is
// not Codeable).
currentDto = formService.getDefinition(definition.getType(), definition.getCode());
}
if (dto instanceof IdmFormAttributeDto) {
IdmFormAttributeDto attribute = (IdmFormAttributeDto) dto;
IdmFormDefinitionDto definition = formService.getDefinition(attribute.getFormDefinition());
if (definition != null) {
// We try to find exists attribute definition by code and form definition.
currentDto = formService.getAttribute(definition, attribute.getCode());
} else {
currentDto = null;
}
}
if (currentDto != null) {
// We found current DTO in IdM.
// Save old and new ID for next DTOs.
context.getReplacedIDs().put((UUID) dto.getId(), (UUID) currentDto.getId());
// We have to change the ID in import DTO.
dto.setId(currentDto.getId());
// Update current DTO by batch DTO.
IdmImportLogDto dtoLog = new IdmImportLogDto(context.getBatch(), dto, RequestOperationType.UPDATE, (UUID) parentDto.getId());
if (!context.isDryRun()) {
// Resolve excluded fields
dto = this.excludeFields(dto, currentDto, context);
// Save a DTO.
dtoService.save(dto);
dtoLog.setResult(new OperationResultDto(OperationState.EXECUTED));
} else {
dtoLog.setResult(new OperationResultDto.Builder(OperationState.NOT_EXECUTED).setModel(//
new DefaultResultModel(CoreResultCode.IMPORT_EXECUTED_AS_DRYRUN)).build());
}
importLogService.saveDistinct(dtoLog);
} else {
IdmImportLogDto dtoLog = new IdmImportLogDto(context.getBatch(), dto, RequestOperationType.ADD, (UUID) parentDto.getId());
// No current DTO was found -> create.
if (!context.isDryRun()) {
// Resolve excluded fields
dto = this.excludeFields(dto, null, context);
// Save new DTO.
dtoService.save(dto);
dtoLog.setResult(new OperationResultDto(OperationState.EXECUTED));
} else {
dtoLog.setResult(new OperationResultDto.Builder(OperationState.NOT_EXECUTED).setModel(//
new DefaultResultModel(CoreResultCode.IMPORT_EXECUTED_AS_DRYRUN)).build());
}
importLogService.saveDistinct(dtoLog);
}
}
} catch (IOException | IllegalArgumentException e) {
throw new ResultCodeException(CoreResultCode.EXPORT_IMPORT_IO_FAILED, e);
}
}
use of eu.bcvsolutions.idm.core.api.exception.ResultCodeException in project CzechIdMng by bcvsolutions.
the class DefaultImportManager method removeRedundant.
/**
* Ensures delete redundant entities in target IdM. Deletes DTOs are within
* golden DTO type (super parent = typically system, role, ...).
*
* @param descriptor
* @param context
*/
private void removeRedundant(ExportDescriptorDto descriptor, ImportContext context) {
Class<? extends BaseDto> dtoClass = descriptor.getDtoClass();
// Does this DTO support the authoritative mode?
boolean supportsAuthoritativeMode = descriptor.isSupportsAuthoritativeMode();
if (!supportsAuthoritativeMode) {
return;
}
String superParentFilterProperty = descriptor.getSuperParentFilterProperty();
Assert.notNull(superParentFilterProperty, "For authoritative mode must be superParentFilterProperty defined!");
// Find super parent (gold) DTO (typically it is DTO for system, role ...)
Class<? extends AbstractDto> superParentDtoClass = getSuperParentDtoClass(descriptor, context);
Assert.notNull(superParentDtoClass, "Supper parent cannot be null here!");
Path superParentDtoTypePath = Paths.get(context.getTempDirectory().toString(), superParentDtoClass.getSimpleName());
try {
// Find all super parent IDs for this DTO type in batch.
Set<UUID> superParentIdsInBatch;
try (Stream<Path> paths = Files.walk(superParentDtoTypePath)) {
superParentIdsInBatch = //
paths.filter(//
Files::isRegularFile).map(path -> {
BaseDto dto = convertFileToDto(path.toFile(), superParentDtoClass, context);
return (UUID) dto.getId();
}).collect(Collectors.toSet());
}
Set<Class<? extends BaseDto>> inheritedClasses = getInheritedClasses(dtoClass, context.getManifest());
// Find all IDs for all children classes
Set<Serializable> childrenIdsInBatch = Sets.newHashSet();
for (Class<? extends BaseDto> inheritedClass : inheritedClasses) {
// Find all IDs for this DTO type in batch.
Path dtoTypePath = Paths.get(context.getTempDirectory().toString(), inheritedClass.getSimpleName());
try (Stream<Path> paths = Files.walk(dtoTypePath)) {
Set<Serializable> childrenIds = //
paths.filter(//
Files::isRegularFile).map(//
path -> convertFileToDto(path.toFile(), inheritedClass, context)).map(dto -> {
// If ID has been replaced, then we need to also replace it.
if (context.getReplacedIDs().containsKey((UUID) dto.getId())) {
return context.getReplacedIDs().get((UUID) dto.getId());
}
return dto.getId();
}).collect(Collectors.toSet());
childrenIdsInBatch.addAll(childrenIds);
}
}
superParentIdsInBatch.forEach(superParentId -> {
try {
Class<? extends BaseDto> serviceDtoClass = dtoClass;
if (dtoClass.isAnnotationPresent(Inheritable.class)) {
serviceDtoClass = dtoClass.getAnnotation(Inheritable.class).dtoService();
}
ReadWriteDtoService<BaseDto, BaseFilter> dtoService = getDtoService(serviceDtoClass);
BaseFilter filterBase = dtoService.getFilterClass().getDeclaredConstructor().newInstance();
// Fill super-parent-property by superParentId (call setter = check if filter is
// implemented).
new PropertyDescriptor(superParentFilterProperty, dtoService.getFilterClass()).getWriteMethod().invoke(filterBase, superParentId);
// Load all IDs in IdM for this parent ID.
List<UUID> childrenIdsInIdM = //
dtoService.find(filterBase, null).getContent().stream().map(//
childDto -> ((AbstractDto) childDto).getId()).collect(Collectors.toList());
// IDs to delete = entities missing in the batch.
Set<UUID> idsToDelete = //
childrenIdsInIdM.stream().filter(//
idmId -> !childrenIdsInBatch.contains(idmId)).collect(Collectors.toSet());
idsToDelete.forEach(id -> {
BaseDto baseDto = dtoService.get(id);
IdmImportLogDto dtoLog = new IdmImportLogDto(context.getBatch(), baseDto, RequestOperationType.REMOVE, superParentId);
if (!context.isDryRun()) {
dtoService.delete(baseDto);
dtoLog.setResult(new OperationResultDto(OperationState.EXECUTED));
} else {
dtoLog.setResult(new OperationResultDto.Builder(OperationState.NOT_EXECUTED).setModel(//
new DefaultResultModel(CoreResultCode.IMPORT_EXECUTED_AS_DRYRUN)).build());
}
importLogService.saveDistinct(dtoLog);
});
} catch (ReflectiveOperationException | IllegalArgumentException | IntrospectionException e) {
throw new ResultCodeException(CoreResultCode.EXPORT_IMPORT_REFLECTION_FAILED, e);
}
});
} catch (IOException e) {
throw new ResultCodeException(CoreResultCode.EXPORT_IMPORT_IO_FAILED, e);
}
}
use of eu.bcvsolutions.idm.core.api.exception.ResultCodeException in project CzechIdMng by bcvsolutions.
the class DefaultIdmRoleTreeNodeService method save.
/**
* Publish {@link RoleTreeNodeEvent} only.
*
* @see {@link RoleTreeNodeSaveProcessor}
*/
@Override
@Transactional(noRollbackFor = AcceptedException.class)
public IdmRoleTreeNodeDto save(IdmRoleTreeNodeDto roleTreeNode, BasePermission... permission) {
Assert.notNull(roleTreeNode, "Automatic role is required.");
checkAccess(toEntity(roleTreeNode, null), permission);
//
LOG.debug("Saving automatic role [{}] - [{}] - [{}]", roleTreeNode.getRole(), roleTreeNode.getTreeNode(), roleTreeNode.getRecursionType());
// FIXME: this should be in save processor ... can be skipped by publishing raw create event
if (isNew(roleTreeNode)) {
// create
EventContext<IdmRoleTreeNodeDto> context = entityEventManager.process(new RoleTreeNodeEvent(RoleTreeNodeEventType.CREATE, roleTreeNode));
if (context.isSuspended()) {
throw new AcceptedException(String.valueOf(context.getContent().getId()));
}
return context.getContent();
}
throw new ResultCodeException(CoreResultCode.METHOD_NOT_ALLOWED, "Automatic role update is not supported");
}
use of eu.bcvsolutions.idm.core.api.exception.ResultCodeException in project CzechIdMng by bcvsolutions.
the class DefaultIdmScriptService method findScripts.
/**
* Return list of {@link IdmScriptType} from resources.
* {@link IdmScriptType} are found by configured locations and by priority - last one wins.
* So default location should be configured first, then external, etc.
*
* @return <code, script>
*/
private Map<String, IdmScriptType> findScripts() {
// last script with the same is used
// => last location has the highest priority
Map<String, IdmScriptType> scripts = new HashMap<>();
//
for (String location : configurationService.getValues(SCRIPT_FOLDER)) {
location = location + configurationService.getValue(SCRIPT_FILE_SUFIX, DEFAULT_SCRIPT_FILE_SUFIX);
Map<String, IdmScriptType> locationScripts = new HashMap<>();
try {
Resource[] resources = applicationContext.getResources(location);
LOG.debug("Found [{}] resources on location [{}]", resources == null ? 0 : resources.length, location);
//
if (ArrayUtils.isEmpty(resources)) {
continue;
}
//
for (Resource resource : resources) {
try {
IdmScriptType scriptType = readType(location, resource.getInputStream());
// log error, if script with the same code was found twice in one resource
if (locationScripts.containsKey(scriptType.getCode())) {
LOG.error("More scripts with code [{}], category [{}] found on the same location [{}].", scriptType.getCode(), scriptType.getCategory(), location);
}
// last one wins
locationScripts.put(scriptType.getCode(), scriptType);
} catch (IOException ex) {
LOG.error("Failed get input stream from, file name [{}].", resource.getFilename(), ex);
}
}
scripts.putAll(locationScripts);
} catch (IOException ex) {
throw new ResultCodeException(CoreResultCode.DEPLOY_ERROR, ImmutableMap.of("path", location), ex);
}
}
return scripts;
}
use of eu.bcvsolutions.idm.core.api.exception.ResultCodeException in project CzechIdMng by bcvsolutions.
the class DefaultRequestManager method executeRequestInternal.
@SuppressWarnings("unchecked")
private IdmRequestDto executeRequestInternal(UUID requestId) {
Assert.notNull(requestId, "Role request ID is required!");
IdmRequestDto request = requestService.get(requestId);
Assert.notNull(request, "Role request is required!");
// Validate request
List<IdmRequestItemDto> items = this.findRequestItems(request.getId(), null);
if (items.isEmpty()) {
throw new ResultCodeException(CoreResultCode.REQUEST_CANNOT_BE_EXECUTED_NONE_ITEMS, ImmutableMap.of("request", request.toString()));
}
List<IdmRequestItemDto> sortedItems = items.stream().sorted(Comparator.comparing(IdmRequestItemDto::getCreated)).collect(Collectors.toList());
// Validate items
//
sortedItems.stream().filter(//
item -> !item.getState().isTerminatedState()).filter(//
item -> !(RequestState.CONCEPT == item.getState() || RequestState.APPROVED == item.getState())).forEach(item -> {
//
throw new ResultCodeException(CoreResultCode.REQUEST_ITEM_CANNOT_BE_EXECUTED, ImmutableMap.of("item", item.toString(), "state", item.getState()));
});
//
sortedItems.stream().filter(item -> RequestOperationType.ADD == item.getOperation() || //
RequestOperationType.UPDATE == item.getOperation()).forEach(item -> {
//
// Get DTO service
Requestable dto = null;
try {
Class<? extends Requestable> dtoClass = (Class<? extends Requestable>) Class.forName(item.getOwnerType());
ReadWriteDtoService<Requestable, BaseFilter> dtoService = (ReadWriteDtoService<Requestable, BaseFilter>) getServiceByItem(item, dtoClass);
dto = this.convertItemToDto(item, dtoClass);
dtoService.validateDto((Requestable) dto);
} catch (Exception e) {
throw new RoleRequestException(CoreResultCode.REQUEST_ITEM_IS_NOT_VALID, ImmutableMap.of("dto", dto != null ? dto.toString() : null, "item", item.toString()), e);
}
});
// We have to ensure the referential integrity, because some items (his DTOs)
// could be child of terminated (Disapproved, Cancelled) item (DTO)
//
sortedItems.stream().filter(// We check terminated ADDed items (Executed state could not yet occur)
item -> item.getState().isTerminatedState()).filter(//
item -> RequestOperationType.ADD == item.getOperation()).filter(//
item -> item.getOwnerId() != null).forEach(terminatedItem -> {
// Create predicate - find all DTOs with that UUID value in any fields
ImmutableList<RequestPredicate> predicates = ImmutableList.of(new RequestPredicate(terminatedItem.getOwnerId(), null));
//
sortedItems.stream().filter(//
item -> !item.getState().isTerminatedState()).filter(item -> {
// Is that item child of terminated item?
try {
Class<? extends Requestable> ownerType = (Class<? extends Requestable>) Class.forName(item.getOwnerType());
Requestable requestable = requestManager.convertItemToDto(item, ownerType);
List<Requestable> filteredDtos = requestManager.filterDtosByPredicates(ImmutableList.of(requestable), ownerType, predicates);
return filteredDtos.contains(requestable);
} catch (ClassNotFoundException | IOException e) {
throw new CoreException(e);
}
}).forEach(itemToCancel -> {
// This item could be not executed, because is use in other
// already terminated (added) item.
itemToCancel.setState(RequestState.CANCELED);
itemToCancel.setResult(new OperationResultDto.Builder(OperationState.NOT_EXECUTED).setException(new RoleRequestException(CoreResultCode.REQUEST_ITEM_NOT_EXECUTED_PARENT_CANCELED, ImmutableMap.of("item", itemToCancel.toString(), "terminatedItem", terminatedItem.toString()))).build());
requestItemService.save(itemToCancel);
});
});
// Reload items ... could be changed
items = this.findRequestItems(request.getId(), null);
List<IdmRequestItemDto> sortedItemsResult = items.stream().sorted(Comparator.comparing(IdmRequestItemDto::getCreated)).collect(Collectors.toList());
//
sortedItemsResult.stream().filter(//
item -> !item.getState().isTerminatedState()).forEach(item -> {
try {
this.resolveItem(item);
} catch (ClassNotFoundException | IOException e) {
throw new CoreException(e);
}
});
request.setState(RequestState.EXECUTED);
request.setResult(new OperationResultDto.Builder(OperationState.EXECUTED).build());
return requestService.save(request);
}
Aggregations