Search in sources :

Example 1 with SubtreeAccessibilityState

use of com.unboundid.ldap.sdk.unboundidds.extensions.SubtreeAccessibilityState in project ldapsdk by pingidentity.

the class MoveSubtree method moveSubtreeWithRestrictedAccessibility.

/**
 * Performs the real {@code moveSubtreeWithRestrictedAccessibility}
 * processing.  If a tool is available, this method will update state
 * information in that tool so that it can be referenced by a shutdown hook
 * in the event that processing is interrupted.
 *
 * @param  tool              A reference to a tool instance to be updated with
 *                           state information.
 * @param  sourceConnection  A connection established to the source server.
 *                           It should be authenticated as a user with
 *                           permission to perform all of the operations
 *                           against the source server as referenced above.
 * @param  targetConnection  A connection established to the target server.
 *                           It should be authenticated as a user with
 *                           permission to perform all of the operations
 *                           against the target server as referenced above.
 * @param  baseDN            The base DN for the subtree to move.
 * @param  sizeLimit         The maximum number of entries to be moved.  It
 *                           may be less than or equal to zero to indicate
 *                           that no client-side limit should be enforced
 *                           (although the server may still enforce its own
 *                           limit).
 * @param  opPurposeControl  An optional operation purpose request control
 *                           that may be included in all requests sent to the
 *                           source and target servers.
 * @param  suppressRefInt    Indicates whether to include a request control
 *                           causing referential integrity updates to be
 *                           suppressed on the source server.
 * @param  listener          An optional listener that may be invoked during
 *                           the course of moving entries from the source
 *                           server to the target server.
 *
 * @return  An object with information about the result of the attempted
 *          subtree move.
 */
@NotNull()
private static MoveSubtreeResult moveSubtreeWithRestrictedAccessibility(@Nullable final MoveSubtree tool, @NotNull final LDAPConnection sourceConnection, @NotNull final LDAPConnection targetConnection, @NotNull final String baseDN, final int sizeLimit, @Nullable final OperationPurposeRequestControl opPurposeControl, final boolean suppressRefInt, @Nullable final MoveSubtreeListener listener) {
    // Ensure that the subtree is currently accessible in both the source and
    // target servers.
    final MoveSubtreeResult initialAccessibilityResult = checkInitialAccessibility(sourceConnection, targetConnection, baseDN, opPurposeControl);
    if (initialAccessibilityResult != null) {
        return initialAccessibilityResult;
    }
    final StringBuilder errorMsg = new StringBuilder();
    final StringBuilder adminMsg = new StringBuilder();
    final ReverseComparator<DN> reverseComparator = new ReverseComparator<>();
    final TreeSet<DN> sourceEntryDNs = new TreeSet<>(reverseComparator);
    final AtomicInteger entriesReadFromSource = new AtomicInteger(0);
    final AtomicInteger entriesAddedToTarget = new AtomicInteger(0);
    final AtomicInteger entriesDeletedFromSource = new AtomicInteger(0);
    final AtomicReference<ResultCode> resultCode = new AtomicReference<>();
    boolean sourceServerAltered = false;
    boolean targetServerAltered = false;
    SubtreeAccessibilityState currentSourceState = SubtreeAccessibilityState.ACCESSIBLE;
    SubtreeAccessibilityState currentTargetState = SubtreeAccessibilityState.ACCESSIBLE;
    processingBlock: {
        // Identify the users authenticated on each connection.
        final String sourceUserDN;
        final String targetUserDN;
        try {
            sourceUserDN = getAuthenticatedUserDN(sourceConnection, true, opPurposeControl);
            targetUserDN = getAuthenticatedUserDN(targetConnection, false, opPurposeControl);
        } catch (final LDAPException le) {
            Debug.debugException(le);
            resultCode.compareAndSet(null, le.getResultCode());
            append(le.getMessage(), errorMsg);
            break processingBlock;
        }
        // Make the subtree hidden on the target server.
        try {
            setAccessibility(targetConnection, false, baseDN, SubtreeAccessibilityState.HIDDEN, targetUserDN, opPurposeControl);
            currentTargetState = SubtreeAccessibilityState.HIDDEN;
            setInterruptMessage(tool, WARN_MOVE_SUBTREE_INTERRUPT_MSG_TARGET_HIDDEN.get(baseDN, targetConnection.getConnectedAddress(), targetConnection.getConnectedPort()));
        } catch (final LDAPException le) {
            Debug.debugException(le);
            resultCode.compareAndSet(null, le.getResultCode());
            append(le.getMessage(), errorMsg);
            break processingBlock;
        }
        // Make the subtree read-only on the source server.
        try {
            setAccessibility(sourceConnection, true, baseDN, SubtreeAccessibilityState.READ_ONLY_BIND_ALLOWED, sourceUserDN, opPurposeControl);
            currentSourceState = SubtreeAccessibilityState.READ_ONLY_BIND_ALLOWED;
            setInterruptMessage(tool, WARN_MOVE_SUBTREE_INTERRUPT_MSG_SOURCE_READ_ONLY.get(baseDN, targetConnection.getConnectedAddress(), targetConnection.getConnectedPort(), sourceConnection.getConnectedAddress(), sourceConnection.getConnectedPort()));
        } catch (final LDAPException le) {
            Debug.debugException(le);
            resultCode.compareAndSet(null, le.getResultCode());
            append(le.getMessage(), errorMsg);
            break processingBlock;
        }
        // Perform a search to find all entries in the target subtree, and include
        // a search listener that will add each entry to the target server as it
        // is returned from the source server.
        final Control[] searchControls;
        if (opPurposeControl == null) {
            searchControls = new Control[] { new DraftLDUPSubentriesRequestControl(true), new ManageDsaITRequestControl(true), new ReturnConflictEntriesRequestControl(true), new SoftDeletedEntryAccessRequestControl(true, true, false), new RealAttributesOnlyRequestControl(true) };
        } else {
            searchControls = new Control[] { new DraftLDUPSubentriesRequestControl(true), new ManageDsaITRequestControl(true), new ReturnConflictEntriesRequestControl(true), new SoftDeletedEntryAccessRequestControl(true, true, false), new RealAttributesOnlyRequestControl(true), opPurposeControl };
        }
        final MoveSubtreeAccessibilitySearchListener searchListener = new MoveSubtreeAccessibilitySearchListener(tool, baseDN, sourceConnection, targetConnection, resultCode, errorMsg, entriesReadFromSource, entriesAddedToTarget, sourceEntryDNs, opPurposeControl, listener);
        final SearchRequest searchRequest = new SearchRequest(searchListener, searchControls, baseDN, SearchScope.SUB, DereferencePolicy.NEVER, sizeLimit, 0, false, Filter.createPresenceFilter("objectClass"), "*", "+");
        SearchResult searchResult;
        try {
            searchResult = sourceConnection.search(searchRequest);
        } catch (final LDAPSearchException lse) {
            Debug.debugException(lse);
            searchResult = lse.getSearchResult();
        }
        if (entriesAddedToTarget.get() > 0) {
            targetServerAltered = true;
        }
        if (searchResult.getResultCode() != ResultCode.SUCCESS) {
            resultCode.compareAndSet(null, searchResult.getResultCode());
            append(ERR_MOVE_SUBTREE_SEARCH_FAILED.get(baseDN, searchResult.getDiagnosticMessage()), errorMsg);
            final AtomicInteger deleteCount = new AtomicInteger(0);
            if (targetServerAltered) {
                deleteEntries(targetConnection, false, sourceEntryDNs, opPurposeControl, false, null, deleteCount, resultCode, errorMsg);
                entriesAddedToTarget.addAndGet(0 - deleteCount.get());
                if (entriesAddedToTarget.get() == 0) {
                    targetServerAltered = false;
                } else {
                    append(ERR_MOVE_SUBTREE_TARGET_NOT_DELETED_ADMIN_ACTION.get(baseDN), adminMsg);
                }
            }
            break processingBlock;
        }
        // If an error occurred during add processing, then fail.
        if (resultCode.get() != null) {
            final AtomicInteger deleteCount = new AtomicInteger(0);
            if (targetServerAltered) {
                deleteEntries(targetConnection, false, sourceEntryDNs, opPurposeControl, false, null, deleteCount, resultCode, errorMsg);
                entriesAddedToTarget.addAndGet(0 - deleteCount.get());
                if (entriesAddedToTarget.get() == 0) {
                    targetServerAltered = false;
                } else {
                    append(ERR_MOVE_SUBTREE_TARGET_NOT_DELETED_ADMIN_ACTION.get(baseDN), adminMsg);
                }
            }
            break processingBlock;
        }
        // Make the subtree read-only on the target server.
        try {
            setAccessibility(targetConnection, true, baseDN, SubtreeAccessibilityState.READ_ONLY_BIND_ALLOWED, targetUserDN, opPurposeControl);
            currentTargetState = SubtreeAccessibilityState.READ_ONLY_BIND_ALLOWED;
            setInterruptMessage(tool, WARN_MOVE_SUBTREE_INTERRUPT_MSG_TARGET_READ_ONLY.get(baseDN, sourceConnection.getConnectedAddress(), sourceConnection.getConnectedPort(), targetConnection.getConnectedAddress(), targetConnection.getConnectedPort()));
        } catch (final LDAPException le) {
            Debug.debugException(le);
            resultCode.compareAndSet(null, le.getResultCode());
            append(le.getMessage(), errorMsg);
            break processingBlock;
        }
        // Make the subtree hidden on the source server.
        try {
            setAccessibility(sourceConnection, true, baseDN, SubtreeAccessibilityState.HIDDEN, sourceUserDN, opPurposeControl);
            currentSourceState = SubtreeAccessibilityState.HIDDEN;
            setInterruptMessage(tool, WARN_MOVE_SUBTREE_INTERRUPT_MSG_SOURCE_HIDDEN.get(baseDN, sourceConnection.getConnectedAddress(), sourceConnection.getConnectedPort(), targetConnection.getConnectedAddress(), targetConnection.getConnectedPort()));
        } catch (final LDAPException le) {
            Debug.debugException(le);
            resultCode.compareAndSet(null, le.getResultCode());
            append(le.getMessage(), errorMsg);
            break processingBlock;
        }
        // Make the subtree accessible on the target server.
        try {
            setAccessibility(targetConnection, true, baseDN, SubtreeAccessibilityState.ACCESSIBLE, targetUserDN, opPurposeControl);
            currentTargetState = SubtreeAccessibilityState.ACCESSIBLE;
            setInterruptMessage(tool, WARN_MOVE_SUBTREE_INTERRUPT_MSG_TARGET_ACCESSIBLE.get(baseDN, sourceConnection.getConnectedAddress(), sourceConnection.getConnectedPort(), targetConnection.getConnectedAddress(), targetConnection.getConnectedPort()));
        } catch (final LDAPException le) {
            Debug.debugException(le);
            resultCode.compareAndSet(null, le.getResultCode());
            append(le.getMessage(), errorMsg);
            break processingBlock;
        }
        // Delete each of the entries in the source server.  The map should
        // already be sorted in reverse order (as a result of the comparator used
        // when creating it), so it will guarantee children are deleted before
        // their parents.
        final boolean deleteSuccessful = deleteEntries(sourceConnection, true, sourceEntryDNs, opPurposeControl, suppressRefInt, listener, entriesDeletedFromSource, resultCode, errorMsg);
        sourceServerAltered = (entriesDeletedFromSource.get() != 0);
        if (!deleteSuccessful) {
            append(ERR_MOVE_SUBTREE_SOURCE_NOT_DELETED_ADMIN_ACTION.get(baseDN), adminMsg);
            break processingBlock;
        }
        // Make the subtree accessible on the source server.
        try {
            setAccessibility(sourceConnection, true, baseDN, SubtreeAccessibilityState.ACCESSIBLE, sourceUserDN, opPurposeControl);
            currentSourceState = SubtreeAccessibilityState.ACCESSIBLE;
            setInterruptMessage(tool, null);
        } catch (final LDAPException le) {
            Debug.debugException(le);
            resultCode.compareAndSet(null, le.getResultCode());
            append(le.getMessage(), errorMsg);
            break processingBlock;
        }
    }
    // then accessible, then generate an admin action message.
    if (currentSourceState != SubtreeAccessibilityState.ACCESSIBLE) {
        if (!sourceServerAltered) {
            try {
                setAccessibility(sourceConnection, true, baseDN, SubtreeAccessibilityState.ACCESSIBLE, null, opPurposeControl);
                currentSourceState = SubtreeAccessibilityState.ACCESSIBLE;
            } catch (final LDAPException le) {
                Debug.debugException(le);
            }
        }
        if (currentSourceState != SubtreeAccessibilityState.ACCESSIBLE) {
            append(ERR_MOVE_SUBTREE_SOURCE_LEFT_INACCESSIBLE.get(currentSourceState, baseDN), adminMsg);
        }
    }
    // then accessible, then generate an admin action message.
    if (currentTargetState != SubtreeAccessibilityState.ACCESSIBLE) {
        if (!targetServerAltered) {
            try {
                setAccessibility(targetConnection, false, baseDN, SubtreeAccessibilityState.ACCESSIBLE, null, opPurposeControl);
                currentTargetState = SubtreeAccessibilityState.ACCESSIBLE;
            } catch (final LDAPException le) {
                Debug.debugException(le);
            }
        }
        if (currentTargetState != SubtreeAccessibilityState.ACCESSIBLE) {
            append(ERR_MOVE_SUBTREE_TARGET_LEFT_INACCESSIBLE.get(currentTargetState, baseDN), adminMsg);
        }
    }
    // Construct the result to return to the client.
    resultCode.compareAndSet(null, ResultCode.SUCCESS);
    final String errorMessage;
    if (errorMsg.length() > 0) {
        errorMessage = errorMsg.toString();
    } else {
        errorMessage = null;
    }
    final String adminActionRequired;
    if (adminMsg.length() > 0) {
        adminActionRequired = adminMsg.toString();
    } else {
        adminActionRequired = null;
    }
    return new MoveSubtreeResult(resultCode.get(), errorMessage, adminActionRequired, sourceServerAltered, targetServerAltered, entriesReadFromSource.get(), entriesAddedToTarget.get(), entriesDeletedFromSource.get());
}
Also used : SearchRequest(com.unboundid.ldap.sdk.SearchRequest) DN(com.unboundid.ldap.sdk.DN) ReverseComparator(com.unboundid.util.ReverseComparator) ASN1OctetString(com.unboundid.asn1.ASN1OctetString) Control(com.unboundid.ldap.sdk.Control) RealAttributesOnlyRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.RealAttributesOnlyRequestControl) OperationPurposeRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.OperationPurposeRequestControl) SuppressReferentialIntegrityUpdatesRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.SuppressReferentialIntegrityUpdatesRequestControl) SoftDeletedEntryAccessRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.SoftDeletedEntryAccessRequestControl) ManageDsaITRequestControl(com.unboundid.ldap.sdk.controls.ManageDsaITRequestControl) ReturnConflictEntriesRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.ReturnConflictEntriesRequestControl) DraftLDUPSubentriesRequestControl(com.unboundid.ldap.sdk.controls.DraftLDUPSubentriesRequestControl) DraftLDUPSubentriesRequestControl(com.unboundid.ldap.sdk.controls.DraftLDUPSubentriesRequestControl) SoftDeletedEntryAccessRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.SoftDeletedEntryAccessRequestControl) TreeSet(java.util.TreeSet) LDAPSearchException(com.unboundid.ldap.sdk.LDAPSearchException) ManageDsaITRequestControl(com.unboundid.ldap.sdk.controls.ManageDsaITRequestControl) ReturnConflictEntriesRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.ReturnConflictEntriesRequestControl) AtomicReference(java.util.concurrent.atomic.AtomicReference) RealAttributesOnlyRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.RealAttributesOnlyRequestControl) SearchResult(com.unboundid.ldap.sdk.SearchResult) SubtreeAccessibilityState(com.unboundid.ldap.sdk.unboundidds.extensions.SubtreeAccessibilityState) LDAPException(com.unboundid.ldap.sdk.LDAPException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ResultCode(com.unboundid.ldap.sdk.ResultCode) NotNull(com.unboundid.util.NotNull)

Example 2 with SubtreeAccessibilityState

use of com.unboundid.ldap.sdk.unboundidds.extensions.SubtreeAccessibilityState in project ldapsdk by pingidentity.

the class SubtreeAccessibility method doSet.

/**
 * Does the work necessary to update a subtree accessibility restriction
 * defined in the server.
 *
 * @param  connection  The connection to use to communicate with the server.
 *
 * @return  A result code with information about the result of operation
 *          processing.
 */
@NotNull()
private ResultCode doSet(@NotNull final LDAPConnection connection) {
    final SubtreeAccessibilityState state = SubtreeAccessibilityState.forName(accessibilityState.getValue());
    if (state == null) {
        // This should never happen.
        err("Unsupported subtree accessibility state ", accessibilityState.getValue());
        return ResultCode.PARAM_ERROR;
    }
    final SetSubtreeAccessibilityExtendedRequest request;
    switch(state) {
        case ACCESSIBLE:
            request = SetSubtreeAccessibilityExtendedRequest.createSetAccessibleRequest(baseDN.getStringValue());
            break;
        case READ_ONLY_BIND_ALLOWED:
            request = SetSubtreeAccessibilityExtendedRequest.createSetReadOnlyRequest(baseDN.getStringValue(), true, bypassUserDN.getStringValue());
            break;
        case READ_ONLY_BIND_DENIED:
            request = SetSubtreeAccessibilityExtendedRequest.createSetReadOnlyRequest(baseDN.getStringValue(), false, bypassUserDN.getStringValue());
            break;
        case HIDDEN:
            request = SetSubtreeAccessibilityExtendedRequest.createSetHiddenRequest(baseDN.getStringValue(), bypassUserDN.getStringValue());
            break;
        default:
            // This should never happen.
            err("Unsupported subtree accessibility state ", state.getStateName());
            return ResultCode.PARAM_ERROR;
    }
    final ExtendedResult result;
    try {
        result = connection.processExtendedOperation(request);
    } catch (final LDAPException le) {
        Debug.debugException(le);
        err("An error occurred while attempting to invoke the set subtree " + "accessibility request:  ", StaticUtils.getExceptionMessage(le));
        return le.getResultCode();
    }
    if (result.getResultCode() == ResultCode.SUCCESS) {
        out("Successfully set an accessibility state of ", state.getStateName(), " for subtree ", baseDN.getStringValue());
    } else {
        out("Unable to set an accessibility state of ", state.getStateName(), " for subtree ", baseDN.getStringValue(), ":  ", result.getDiagnosticMessage());
    }
    return result.getResultCode();
}
Also used : LDAPException(com.unboundid.ldap.sdk.LDAPException) SetSubtreeAccessibilityExtendedRequest(com.unboundid.ldap.sdk.unboundidds.extensions.SetSubtreeAccessibilityExtendedRequest) ExtendedResult(com.unboundid.ldap.sdk.ExtendedResult) GetSubtreeAccessibilityExtendedResult(com.unboundid.ldap.sdk.unboundidds.extensions.GetSubtreeAccessibilityExtendedResult) SubtreeAccessibilityState(com.unboundid.ldap.sdk.unboundidds.extensions.SubtreeAccessibilityState) NotNull(com.unboundid.util.NotNull)

Aggregations

LDAPException (com.unboundid.ldap.sdk.LDAPException)2 SubtreeAccessibilityState (com.unboundid.ldap.sdk.unboundidds.extensions.SubtreeAccessibilityState)2 NotNull (com.unboundid.util.NotNull)2 ASN1OctetString (com.unboundid.asn1.ASN1OctetString)1 Control (com.unboundid.ldap.sdk.Control)1 DN (com.unboundid.ldap.sdk.DN)1 ExtendedResult (com.unboundid.ldap.sdk.ExtendedResult)1 LDAPSearchException (com.unboundid.ldap.sdk.LDAPSearchException)1 ResultCode (com.unboundid.ldap.sdk.ResultCode)1 SearchRequest (com.unboundid.ldap.sdk.SearchRequest)1 SearchResult (com.unboundid.ldap.sdk.SearchResult)1 DraftLDUPSubentriesRequestControl (com.unboundid.ldap.sdk.controls.DraftLDUPSubentriesRequestControl)1 ManageDsaITRequestControl (com.unboundid.ldap.sdk.controls.ManageDsaITRequestControl)1 OperationPurposeRequestControl (com.unboundid.ldap.sdk.unboundidds.controls.OperationPurposeRequestControl)1 RealAttributesOnlyRequestControl (com.unboundid.ldap.sdk.unboundidds.controls.RealAttributesOnlyRequestControl)1 ReturnConflictEntriesRequestControl (com.unboundid.ldap.sdk.unboundidds.controls.ReturnConflictEntriesRequestControl)1 SoftDeletedEntryAccessRequestControl (com.unboundid.ldap.sdk.unboundidds.controls.SoftDeletedEntryAccessRequestControl)1 SuppressReferentialIntegrityUpdatesRequestControl (com.unboundid.ldap.sdk.unboundidds.controls.SuppressReferentialIntegrityUpdatesRequestControl)1 GetSubtreeAccessibilityExtendedResult (com.unboundid.ldap.sdk.unboundidds.extensions.GetSubtreeAccessibilityExtendedResult)1 SetSubtreeAccessibilityExtendedRequest (com.unboundid.ldap.sdk.unboundidds.extensions.SetSubtreeAccessibilityExtendedRequest)1