use of org.apache.commons.configuration2.interpol.InterpolatorSpecification in project midpoint by Evolveum.
the class NodeIdComputer method getNodeIdFromExpression.
private String getNodeIdFromExpression(ConfigurationInterpolator parentInterpolator, String expression, OperationResult result) {
SequenceLookup sequenceLookup = new SequenceLookup();
InterpolatorSpecification sequenceProvidingInterpolatorSpec = new InterpolatorSpecification.Builder().withParentInterpolator(parentInterpolator).withPrefixLookup("sequence", sequenceLookup).create();
ConfigurationInterpolator interpolator = ConfigurationInterpolator.fromSpecification(sequenceProvidingInterpolatorSpec);
for (int attempt = 0; ; attempt++) {
Object interpolationResult = interpolator.interpolate(expression);
if (!(interpolationResult instanceof String)) {
LOGGER.warn("Node ID expression '{}' returned null or non-String value: {}", expression, interpolationResult);
return null;
}
String candidateNodeId = (String) interpolationResult;
if (candidateNodeId.contains("${")) {
// This is a bit of hack: it looks like the node was not resolved correctly.
throw new SystemException("Looks like we couldn't resolve the node ID expression. The (partial) result is: '" + candidateNodeId + "'");
}
if (sequenceLookup.iterationRequired) {
try {
// Let us try to create node with given name. If we fail we know we need to iterate.
// If we succeed, we will (later) replace the node with the correct content.
// Note that we set (fake) last check-in time here so this node will not be accidentally cleaned-up.
// TODO consider moving this addObject call to NodeRegistrar (requires cleanup of the mix of
// Spring injected and manually created objects)
NodeType node = new NodeType(prismContext).name(candidateNodeId).lastCheckInTime(XmlTypeConverter.createXMLGregorianCalendar());
repositoryService.addObject(node.asPrismObject(), null, result);
} catch (ObjectAlreadyExistsException e) {
// We have a conflict. But the node might be - in fact - dead. So let's try to reclaim it if possible.
String nodeIdNorm = prismContext.getDefaultPolyStringNormalizer().normalize(candidateNodeId);
SearchResultList<PrismObject<NodeType>> existingNodes;
try {
existingNodes = repositoryService.searchObjects(NodeType.class, prismContext.queryFor(NodeType.class).item(NodeType.F_NAME).eqPoly(candidateNodeId, nodeIdNorm).matchingNorm().build(), null, result);
} catch (SchemaException ex) {
throw new SystemException("Unexpected schema exception while looking for node '" + candidateNodeId + "': " + e.getMessage(), e);
}
if (existingNodes.isEmpty()) {
// Strange. The node should have gone in the meanwhile. To be safe, let's try another one.
LOGGER.warn("Node name '{}' seemed to be already reserved. But it cannot be found now. Iterating to the" + " next one (if possible).", candidateNodeId);
sequenceLookup.advance();
} else if (existingNodes.size() > 1) {
LOGGER.warn("Strange: More than one node with the name of '{}': {}. Trying next name in the sequence" + "(if possible).", candidateNodeId, existingNodes);
sequenceLookup.advance();
} else {
NodeType existingNode = existingNodes.get(0).asObjectable();
if (existingNode.getOperationalState() == NodeOperationalStateType.DOWN) {
LOGGER.info("Considering using the node name of '{}' that already exists but is marked as being down" + " (OID {}). So deleting the node and trying again.", candidateNodeId, existingNode.getOid());
try {
repositoryService.deleteObject(NodeType.class, existingNode.getOid(), result);
} catch (ObjectNotFoundException ex) {
LoggingUtils.logExceptionAsWarning(LOGGER, "Couldn't delete the node {}. Probably someone" + " else is faster than us.", ex, existingNode);
}
// no advance here
} else {
LOGGER.debug("Node name '{}' is already reserved. Iterating to next one (if possible).", candidateNodeId);
sequenceLookup.advance();
}
}
if (attempt > MAX_ATTEMPTS_SAFEGUARD) {
throw new SystemException("Maximum attempts safeguard value of " + MAX_ATTEMPTS_SAFEGUARD + " has been reached. " + "Something very strange must have happened.");
} else if (sequenceLookup.isOutOfNumbers()) {
throw new SystemException("Cannot acquire node name. The sequence upper border (" + sequenceLookup.end + ") has been reached.");
} else {
continue;
}
} catch (SchemaException e) {
throw new SystemException("Unexpected schema exception while creating temporary node: " + e.getMessage(), e);
}
}
return candidateNodeId;
}
}
Aggregations