Search in sources :

Example 1 with InterpolatorSpecification

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;
    }
}
Also used : SchemaException(com.evolveum.midpoint.util.exception.SchemaException) SearchResultList(com.evolveum.midpoint.schema.SearchResultList) SystemException(com.evolveum.midpoint.util.exception.SystemException) InterpolatorSpecification(org.apache.commons.configuration2.interpol.InterpolatorSpecification) NodeType(com.evolveum.midpoint.xml.ns._public.common.common_3.NodeType) ObjectNotFoundException(com.evolveum.midpoint.util.exception.ObjectNotFoundException) PrismObject(com.evolveum.midpoint.prism.PrismObject) ConfigurationInterpolator(org.apache.commons.configuration2.interpol.ConfigurationInterpolator) ObjectAlreadyExistsException(com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException)

Aggregations

PrismObject (com.evolveum.midpoint.prism.PrismObject)1 SearchResultList (com.evolveum.midpoint.schema.SearchResultList)1 ObjectAlreadyExistsException (com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException)1 ObjectNotFoundException (com.evolveum.midpoint.util.exception.ObjectNotFoundException)1 SchemaException (com.evolveum.midpoint.util.exception.SchemaException)1 SystemException (com.evolveum.midpoint.util.exception.SystemException)1 NodeType (com.evolveum.midpoint.xml.ns._public.common.common_3.NodeType)1 ConfigurationInterpolator (org.apache.commons.configuration2.interpol.ConfigurationInterpolator)1 InterpolatorSpecification (org.apache.commons.configuration2.interpol.InterpolatorSpecification)1