Search in sources :

Example 1 with SoftDeletedEntryAccessRequestControl

use of com.unboundid.ldap.sdk.unboundidds.controls.SoftDeletedEntryAccessRequestControl in project ldapsdk by pingidentity.

the class SubtreeDeleter method delete.

/**
 * Attempts to delete the specified subtree using the current settings.
 *
 * @param  connection
 *              The {@link LDAPInterface} instance to use to communicate with
 *              the directory server.  While this may be an individual
 *              {@link LDAPConnection}, it may be better as a connection
 *              pool with automatic retry enabled so that it's more likely to
 *              succeed in the event that a connection becomes invalid or an
 *              operation experiences a transient failure.  It must not be
 *              {@code null}.
 * @param  baseDN
 *              The base DN for the subtree to delete.  It must not be
 *              {@code null}.
 *
 * @return  An object with information about the results of the subtree
 *          delete processing.
 */
@NotNull()
public SubtreeDeleterResult delete(@NotNull final LDAPInterface connection, @NotNull final DN baseDN) {
    final AtomicReference<RootDSE> rootDSE = new AtomicReference<>();
    final boolean useSetSubtreeAccessibility = useSetSubtreeAccessibilityOperationIfAvailable && supportsExtendedRequest(connection, rootDSE, SetSubtreeAccessibilityExtendedRequest.SET_SUBTREE_ACCESSIBILITY_REQUEST_OID) && supportsExtendedRequest(connection, rootDSE, WhoAmIExtendedRequest.WHO_AM_I_REQUEST_OID);
    final boolean usePagedResults = useSimplePagedResultsControlIfAvailable && supportsControl(connection, rootDSE, SimplePagedResultsControl.PAGED_RESULTS_OID);
    final boolean useSubentries = useSubentriesControlIfAvailable && supportsControl(connection, rootDSE, DraftLDUPSubentriesRequestControl.SUBENTRIES_REQUEST_OID);
    final List<Control> searchControls = new ArrayList<>(10);
    searchControls.addAll(additionalSearchControls);
    final List<Control> deleteControls = new ArrayList<>(10);
    deleteControls.addAll(additionalDeleteControls);
    if (useHardDeleteControlIfAvailable && supportsControl(connection, rootDSE, HardDeleteRequestControl.HARD_DELETE_REQUEST_OID)) {
        deleteControls.add(new HardDeleteRequestControl(false));
    }
    if (useManageDSAITControlIfAvailable && supportsControl(connection, rootDSE, ManageDsaITRequestControl.MANAGE_DSA_IT_REQUEST_OID)) {
        final ManageDsaITRequestControl c = new ManageDsaITRequestControl(false);
        searchControls.add(c);
        deleteControls.add(c);
    }
    if (usePermitUnindexedSearchControlIfAvailable && supportsControl(connection, rootDSE, PermitUnindexedSearchRequestControl.PERMIT_UNINDEXED_SEARCH_REQUEST_OID)) {
        searchControls.add(new PermitUnindexedSearchRequestControl(false));
    }
    if (useReturnConflictEntriesRequestControlIfAvailable && supportsControl(connection, rootDSE, ReturnConflictEntriesRequestControl.RETURN_CONFLICT_ENTRIES_REQUEST_OID)) {
        searchControls.add(new ReturnConflictEntriesRequestControl(false));
    }
    if (useSoftDeletedEntryAccessControlIfAvailable && supportsControl(connection, rootDSE, SoftDeletedEntryAccessRequestControl.SOFT_DELETED_ENTRY_ACCESS_REQUEST_OID)) {
        searchControls.add(new SoftDeletedEntryAccessRequestControl(false, true, false));
    }
    return delete(connection, baseDN, deleteBaseEntry, useSetSubtreeAccessibility, usePagedResults, searchRequestSizeLimit, simplePagedResultsPageSize, useSubentries, searchControls, deleteControls, deleteRateLimiter);
}
Also used : PermitUnindexedSearchRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.PermitUnindexedSearchRequestControl) Control(com.unboundid.ldap.sdk.Control) SimplePagedResultsControl(com.unboundid.ldap.sdk.controls.SimplePagedResultsControl) HardDeleteRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.HardDeleteRequestControl) 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) SoftDeletedEntryAccessRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.SoftDeletedEntryAccessRequestControl) HardDeleteRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.HardDeleteRequestControl) PermitUnindexedSearchRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.PermitUnindexedSearchRequestControl) ArrayList(java.util.ArrayList) ReturnConflictEntriesRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.ReturnConflictEntriesRequestControl) AtomicReference(java.util.concurrent.atomic.AtomicReference) RootDSE(com.unboundid.ldap.sdk.RootDSE) ManageDsaITRequestControl(com.unboundid.ldap.sdk.controls.ManageDsaITRequestControl)

Example 2 with SoftDeletedEntryAccessRequestControl

use of com.unboundid.ldap.sdk.unboundidds.controls.SoftDeletedEntryAccessRequestControl in project ldapsdk by pingidentity.

the class LDAPSearch method getSearchControls.

/**
 * Retrieves a list of the controls that should be used when processing search
 * operations.
 *
 * @return  A list of the controls that should be used when processing search
 *          operations.
 *
 * @throws  LDAPException  If a problem is encountered while generating the
 *                         controls for a search request.
 */
@NotNull()
private List<Control> getSearchControls() {
    final ArrayList<Control> controls = new ArrayList<>(10);
    if (searchControl.isPresent()) {
        controls.addAll(searchControl.getValues());
    }
    if (joinRequestControl != null) {
        controls.add(joinRequestControl);
    }
    if (matchedValuesRequestControl != null) {
        controls.add(matchedValuesRequestControl);
    }
    if (matchingEntryCountRequestControl != null) {
        controls.add(matchingEntryCountRequestControl);
    }
    if (overrideSearchLimitsRequestControl != null) {
        controls.add(overrideSearchLimitsRequestControl);
    }
    if (persistentSearchRequestControl != null) {
        controls.add(persistentSearchRequestControl);
    }
    if (sortRequestControl != null) {
        controls.add(sortRequestControl);
    }
    if (vlvRequestControl != null) {
        controls.add(vlvRequestControl);
    }
    controls.addAll(routeToBackendSetRequestControls);
    if (accountUsable.isPresent()) {
        controls.add(new AccountUsableRequestControl(true));
    }
    if (getBackendSetID.isPresent()) {
        controls.add(new GetBackendSetIDRequestControl(false));
    }
    if (getServerID.isPresent()) {
        controls.add(new GetServerIDRequestControl(false));
    }
    if (includeReplicationConflictEntries.isPresent()) {
        controls.add(new ReturnConflictEntriesRequestControl(true));
    }
    if (includeSoftDeletedEntries.isPresent()) {
        final String valueStr = StaticUtils.toLowerCase(includeSoftDeletedEntries.getValue());
        if (valueStr.equals("with-non-deleted-entries")) {
            controls.add(new SoftDeletedEntryAccessRequestControl(true, true, false));
        } else if (valueStr.equals("without-non-deleted-entries")) {
            controls.add(new SoftDeletedEntryAccessRequestControl(true, false, false));
        } else {
            controls.add(new SoftDeletedEntryAccessRequestControl(true, false, true));
        }
    }
    if (draftLDUPSubentries.isPresent()) {
        controls.add(new DraftLDUPSubentriesRequestControl(true));
    }
    if (rfc3672Subentries.isPresent()) {
        controls.add(new RFC3672SubentriesRequestControl(rfc3672Subentries.getValue()));
    }
    if (manageDsaIT.isPresent()) {
        controls.add(new ManageDsaITRequestControl(true));
    }
    if (realAttributesOnly.isPresent()) {
        controls.add(new RealAttributesOnlyRequestControl(true));
    }
    if (routeToServer.isPresent()) {
        controls.add(new RouteToServerRequestControl(false, routeToServer.getValue(), false, false, false));
    }
    if (virtualAttributesOnly.isPresent()) {
        controls.add(new VirtualAttributesOnlyRequestControl(true));
    }
    if (excludeBranch.isPresent()) {
        final ArrayList<String> dns = new ArrayList<>(excludeBranch.getValues().size());
        for (final DN dn : excludeBranch.getValues()) {
            dns.add(dn.toString());
        }
        controls.add(new ExcludeBranchRequestControl(true, dns));
    }
    if (assertionFilter.isPresent()) {
        controls.add(new AssertionRequestControl(assertionFilter.getValue(), true));
    }
    if (getEffectiveRightsAuthzID.isPresent()) {
        final String[] attributes;
        if (getEffectiveRightsAttribute.isPresent()) {
            attributes = new String[getEffectiveRightsAttribute.getValues().size()];
            for (int i = 0; i < attributes.length; i++) {
                attributes[i] = getEffectiveRightsAttribute.getValues().get(i);
            }
        } else {
            attributes = StaticUtils.NO_STRINGS;
        }
        controls.add(new GetEffectiveRightsRequestControl(true, getEffectiveRightsAuthzID.getValue(), attributes));
    }
    if (operationPurpose.isPresent()) {
        controls.add(new OperationPurposeRequestControl(true, "ldapsearch", Version.NUMERIC_VERSION_STRING, "LDAPSearch.getSearchControls", operationPurpose.getValue()));
    }
    if (proxyAs.isPresent()) {
        controls.add(new ProxiedAuthorizationV2RequestControl(proxyAs.getValue()));
    }
    if (proxyV1As.isPresent()) {
        controls.add(new ProxiedAuthorizationV1RequestControl(proxyV1As.getValue()));
    }
    if (suppressOperationalAttributeUpdates.isPresent()) {
        final EnumSet<SuppressType> suppressTypes = EnumSet.noneOf(SuppressType.class);
        for (final String s : suppressOperationalAttributeUpdates.getValues()) {
            if (s.equalsIgnoreCase("last-access-time")) {
                suppressTypes.add(SuppressType.LAST_ACCESS_TIME);
            } else if (s.equalsIgnoreCase("last-login-time")) {
                suppressTypes.add(SuppressType.LAST_LOGIN_TIME);
            } else if (s.equalsIgnoreCase("last-login-ip")) {
                suppressTypes.add(SuppressType.LAST_LOGIN_IP);
            }
        }
        controls.add(new SuppressOperationalAttributeUpdateRequestControl(suppressTypes));
    }
    if (rejectUnindexedSearch.isPresent()) {
        controls.add(new RejectUnindexedSearchRequestControl());
    }
    if (permitUnindexedSearch.isPresent()) {
        controls.add(new PermitUnindexedSearchRequestControl());
    }
    return controls;
}
Also used : RouteToServerRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.RouteToServerRequestControl) ArrayList(java.util.ArrayList) ProxiedAuthorizationV2RequestControl(com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV2RequestControl) JoinBaseDN(com.unboundid.ldap.sdk.unboundidds.controls.JoinBaseDN) DN(com.unboundid.ldap.sdk.DN) ASN1OctetString(com.unboundid.asn1.ASN1OctetString) GetEffectiveRightsRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.GetEffectiveRightsRequestControl) VirtualListViewRequestControl(com.unboundid.ldap.sdk.controls.VirtualListViewRequestControl) RouteToServerRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.RouteToServerRequestControl) RFC3672SubentriesRequestControl(com.unboundid.ldap.sdk.controls.RFC3672SubentriesRequestControl) SimplePagedResultsControl(com.unboundid.ldap.sdk.controls.SimplePagedResultsControl) MatchingEntryCountRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.MatchingEntryCountRequestControl) MatchedValuesRequestControl(com.unboundid.ldap.sdk.controls.MatchedValuesRequestControl) VirtualAttributesOnlyRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.VirtualAttributesOnlyRequestControl) AccountUsableRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.AccountUsableRequestControl) OverrideSearchLimitsRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.OverrideSearchLimitsRequestControl) SuppressOperationalAttributeUpdateRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.SuppressOperationalAttributeUpdateRequestControl) ProxiedAuthorizationV1RequestControl(com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV1RequestControl) OperationPurposeRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.OperationPurposeRequestControl) SoftDeletedEntryAccessRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.SoftDeletedEntryAccessRequestControl) JoinRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.JoinRequestControl) ReturnConflictEntriesRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.ReturnConflictEntriesRequestControl) GetRecentLoginHistoryRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.GetRecentLoginHistoryRequestControl) PermitUnindexedSearchRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.PermitUnindexedSearchRequestControl) RejectUnindexedSearchRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.RejectUnindexedSearchRequestControl) AuthorizationIdentityRequestControl(com.unboundid.ldap.sdk.controls.AuthorizationIdentityRequestControl) Control(com.unboundid.ldap.sdk.Control) GetUserResourceLimitsRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.GetUserResourceLimitsRequestControl) GetBackendSetIDRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.GetBackendSetIDRequestControl) GetAuthorizationEntryRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.GetAuthorizationEntryRequestControl) RealAttributesOnlyRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.RealAttributesOnlyRequestControl) ExcludeBranchRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.ExcludeBranchRequestControl) ProxiedAuthorizationV2RequestControl(com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV2RequestControl) ServerSideSortRequestControl(com.unboundid.ldap.sdk.controls.ServerSideSortRequestControl) GetServerIDRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.GetServerIDRequestControl) PasswordPolicyRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.PasswordPolicyRequestControl) AssertionRequestControl(com.unboundid.ldap.sdk.controls.AssertionRequestControl) RouteToBackendSetRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.RouteToBackendSetRequestControl) ManageDsaITRequestControl(com.unboundid.ldap.sdk.controls.ManageDsaITRequestControl) PersistentSearchRequestControl(com.unboundid.ldap.sdk.controls.PersistentSearchRequestControl) GetEffectiveRightsRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.GetEffectiveRightsRequestControl) DraftLDUPSubentriesRequestControl(com.unboundid.ldap.sdk.controls.DraftLDUPSubentriesRequestControl) AssertionRequestControl(com.unboundid.ldap.sdk.controls.AssertionRequestControl) DraftLDUPSubentriesRequestControl(com.unboundid.ldap.sdk.controls.DraftLDUPSubentriesRequestControl) SoftDeletedEntryAccessRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.SoftDeletedEntryAccessRequestControl) GetServerIDRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.GetServerIDRequestControl) ManageDsaITRequestControl(com.unboundid.ldap.sdk.controls.ManageDsaITRequestControl) AccountUsableRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.AccountUsableRequestControl) PermitUnindexedSearchRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.PermitUnindexedSearchRequestControl) ReturnConflictEntriesRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.ReturnConflictEntriesRequestControl) RealAttributesOnlyRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.RealAttributesOnlyRequestControl) SuppressType(com.unboundid.ldap.sdk.unboundidds.controls.SuppressType) SuppressOperationalAttributeUpdateRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.SuppressOperationalAttributeUpdateRequestControl) OperationPurposeRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.OperationPurposeRequestControl) ProxiedAuthorizationV1RequestControl(com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV1RequestControl) RFC3672SubentriesRequestControl(com.unboundid.ldap.sdk.controls.RFC3672SubentriesRequestControl) GetBackendSetIDRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.GetBackendSetIDRequestControl) ExcludeBranchRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.ExcludeBranchRequestControl) RejectUnindexedSearchRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.RejectUnindexedSearchRequestControl) VirtualAttributesOnlyRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.VirtualAttributesOnlyRequestControl) NotNull(com.unboundid.util.NotNull)

Example 3 with SoftDeletedEntryAccessRequestControl

use of com.unboundid.ldap.sdk.unboundidds.controls.SoftDeletedEntryAccessRequestControl 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 4 with SoftDeletedEntryAccessRequestControl

use of com.unboundid.ldap.sdk.unboundidds.controls.SoftDeletedEntryAccessRequestControl in project ldapsdk by pingidentity.

the class MoveSubtree method moveEntryWithInteractiveTransaction.

/**
 * <BLOCKQUOTE>
 *   <B>NOTE:</B>  The use of interactive transactions is strongly discouraged
 *   because it can create conditions which are prone to deadlocks between
 *   operations that may significantly affect performance and will result in
 *   the cancellation of one or both operations.  Use one of the
 *   {@code moveSubtreeWithRestrictedAccessibility} methods instead.
 * </BLOCKQUOTE>
 * Moves a single leaf entry using a pair of interactive transactions.  The
 * logic used to accomplish this is as follows:
 * <OL>
 *   <LI>Start an interactive transaction in the source server.</LI>
 *   <LI>Start an interactive transaction in the target server.</LI>
 *   <LI>Read the entry from the source server.  The search request will have
 *       a subtree scope with a size limit of one, a filter of
 *       "(objectClass=*)", will request all user and operational attributes,
 *       and will include the following request controls:  interactive
 *       transaction specification, ManageDsaIT, LDAP subentries, return
 *       conflict entries, soft-deleted entry access, real attributes only,
 *       and operation purpose.</LI>
 *  <LI>Add the entry to the target server.  The add request will include the
 *      following controls:  interactive transaction specification, ignore
 *      NO-USER-MODIFICATION, and operation purpose.</LI>
 *  <LI>Delete the entry from the source server.  The delete request will
 *      include the following controls:  interactive transaction
 *      specification, ManageDsaIT, and operation purpose.</LI>
 *  <LI>Commit the interactive transaction in the target server.</LI>
 *  <LI>Commit the interactive transaction in the source server.</LI>
 * </OL>
 * Conditions which could result in an incomplete move include:
 * <UL>
 *   <LI>The commit in the target server succeeds but the commit in the
 *       source server fails.  In this case, the entry may end up in both
 *       servers, requiring manual cleanup.  If this occurs, then the result
 *       returned from this method will indicate this condition.</LI>
 *   <LI>The account used to read entries from the source server does not have
 *       permission to see all attributes in all entries.  In this case, the
 *       target server will include only a partial representation of the entry
 *       in the source server.  To avoid this problem, ensure that the account
 *       used to read from the source server has sufficient access rights to
 *       see all attributes in the entry to move.</LI>
 *   <LI>The source server participates in replication and a change occurs to
 *       the entry in a different server in the replicated environment while
 *       the move is in progress.  In this case, those changes may not be
 *       reflected in the target server.  To avoid this problem, it is
 *       strongly recommended that all write access in the replication
 *       environment containing the source server be directed to the source
 *       server during the time that the move is in progress (e.g., using a
 *       failover load-balancing algorithm in the Directory Proxy
 *       Server).</LI>
 * </UL>
 *
 * @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  entryDN           The base DN for the subtree to move.
 * @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.
 *
 * @deprecated  The use of interactive transactions is strongly discouraged
 *              because it can create conditions which are prone to deadlocks
 *              between operations that may significantly affect performance
 *              and will result in the cancellation of one or both operations.
 */
@Deprecated()
@SuppressWarnings("deprecation")
@NotNull()
public static MoveSubtreeResult moveEntryWithInteractiveTransaction(@NotNull final LDAPConnection sourceConnection, @NotNull final LDAPConnection targetConnection, @NotNull final String entryDN, @Nullable final OperationPurposeRequestControl opPurposeControl, final boolean suppressRefInt, @Nullable final MoveSubtreeListener listener) {
    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<>();
    ASN1OctetString sourceTxnID = null;
    ASN1OctetString targetTxnID = null;
    boolean sourceServerAltered = false;
    boolean targetServerAltered = false;
    processingBlock: try {
        // Start an interactive transaction in the source server.
        final com.unboundid.ldap.sdk.unboundidds.controls.InteractiveTransactionSpecificationRequestControl sourceTxnControl;
        try {
            final com.unboundid.ldap.sdk.unboundidds.extensions.StartInteractiveTransactionExtendedRequest startTxnRequest;
            if (opPurposeControl == null) {
                startTxnRequest = new com.unboundid.ldap.sdk.unboundidds.extensions.StartInteractiveTransactionExtendedRequest(entryDN);
            } else {
                startTxnRequest = new com.unboundid.ldap.sdk.unboundidds.extensions.StartInteractiveTransactionExtendedRequest(entryDN, new Control[] { opPurposeControl });
            }
            final com.unboundid.ldap.sdk.unboundidds.extensions.StartInteractiveTransactionExtendedResult startTxnResult = (com.unboundid.ldap.sdk.unboundidds.extensions.StartInteractiveTransactionExtendedResult) sourceConnection.processExtendedOperation(startTxnRequest);
            if (startTxnResult.getResultCode() == ResultCode.SUCCESS) {
                sourceTxnID = startTxnResult.getTransactionID();
                sourceTxnControl = new com.unboundid.ldap.sdk.unboundidds.controls.InteractiveTransactionSpecificationRequestControl(sourceTxnID, true, true);
            } else {
                resultCode.compareAndSet(null, startTxnResult.getResultCode());
                append(ERR_MOVE_ENTRY_CANNOT_START_SOURCE_TXN.get(startTxnResult.getDiagnosticMessage()), errorMsg);
                break processingBlock;
            }
        } catch (final LDAPException le) {
            Debug.debugException(le);
            resultCode.compareAndSet(null, le.getResultCode());
            append(ERR_MOVE_ENTRY_CANNOT_START_SOURCE_TXN.get(StaticUtils.getExceptionMessage(le)), errorMsg);
            break processingBlock;
        }
        // Start an interactive transaction in the target server.
        final com.unboundid.ldap.sdk.unboundidds.controls.InteractiveTransactionSpecificationRequestControl targetTxnControl;
        try {
            final com.unboundid.ldap.sdk.unboundidds.extensions.StartInteractiveTransactionExtendedRequest startTxnRequest;
            if (opPurposeControl == null) {
                startTxnRequest = new com.unboundid.ldap.sdk.unboundidds.extensions.StartInteractiveTransactionExtendedRequest(entryDN);
            } else {
                startTxnRequest = new com.unboundid.ldap.sdk.unboundidds.extensions.StartInteractiveTransactionExtendedRequest(entryDN, new Control[] { opPurposeControl });
            }
            final com.unboundid.ldap.sdk.unboundidds.extensions.StartInteractiveTransactionExtendedResult startTxnResult = (com.unboundid.ldap.sdk.unboundidds.extensions.StartInteractiveTransactionExtendedResult) targetConnection.processExtendedOperation(startTxnRequest);
            if (startTxnResult.getResultCode() == ResultCode.SUCCESS) {
                targetTxnID = startTxnResult.getTransactionID();
                targetTxnControl = new com.unboundid.ldap.sdk.unboundidds.controls.InteractiveTransactionSpecificationRequestControl(targetTxnID, true, true);
            } else {
                resultCode.compareAndSet(null, startTxnResult.getResultCode());
                append(ERR_MOVE_ENTRY_CANNOT_START_TARGET_TXN.get(startTxnResult.getDiagnosticMessage()), errorMsg);
                break processingBlock;
            }
        } catch (final LDAPException le) {
            Debug.debugException(le);
            resultCode.compareAndSet(null, le.getResultCode());
            append(ERR_MOVE_ENTRY_CANNOT_START_TARGET_TXN.get(StaticUtils.getExceptionMessage(le)), 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[] { sourceTxnControl, new DraftLDUPSubentriesRequestControl(true), new ManageDsaITRequestControl(true), new ReturnConflictEntriesRequestControl(true), new SoftDeletedEntryAccessRequestControl(true, true, false), new RealAttributesOnlyRequestControl(true) };
        } else {
            searchControls = new Control[] { sourceTxnControl, new DraftLDUPSubentriesRequestControl(true), new ManageDsaITRequestControl(true), new ReturnConflictEntriesRequestControl(true), new SoftDeletedEntryAccessRequestControl(true, true, false), new RealAttributesOnlyRequestControl(true), opPurposeControl };
        }
        final MoveSubtreeTxnSearchListener searchListener = new MoveSubtreeTxnSearchListener(targetConnection, resultCode, errorMsg, entriesReadFromSource, entriesAddedToTarget, sourceEntryDNs, targetTxnControl, opPurposeControl, listener);
        final SearchRequest searchRequest = new SearchRequest(searchListener, searchControls, entryDN, SearchScope.SUB, DereferencePolicy.NEVER, 1, 0, false, Filter.createPresenceFilter("objectClass"), "*", "+");
        SearchResult searchResult;
        try {
            searchResult = sourceConnection.search(searchRequest);
        } catch (final LDAPSearchException lse) {
            Debug.debugException(lse);
            searchResult = lse.getSearchResult();
        }
        if (searchResult.getResultCode() == ResultCode.SUCCESS) {
            try {
                final com.unboundid.ldap.sdk.unboundidds.controls.InteractiveTransactionSpecificationResponseControl txnResult = com.unboundid.ldap.sdk.unboundidds.controls.InteractiveTransactionSpecificationResponseControl.get(searchResult);
                if ((txnResult == null) || (!txnResult.transactionValid())) {
                    resultCode.compareAndSet(null, ResultCode.LOCAL_ERROR);
                    append(ERR_MOVE_ENTRY_SEARCH_TXN_NO_LONGER_VALID.get(), errorMsg);
                    break processingBlock;
                }
            } catch (final LDAPException le) {
                Debug.debugException(le);
                resultCode.compareAndSet(null, le.getResultCode());
                append(ERR_MOVE_ENTRY_CANNOT_DECODE_SEARCH_TXN_CONTROL.get(StaticUtils.getExceptionMessage(le)), errorMsg);
                break processingBlock;
            }
        } else {
            resultCode.compareAndSet(null, searchResult.getResultCode());
            append(ERR_MOVE_SUBTREE_SEARCH_FAILED.get(entryDN, searchResult.getDiagnosticMessage()), errorMsg);
            try {
                final com.unboundid.ldap.sdk.unboundidds.controls.InteractiveTransactionSpecificationResponseControl txnResult = com.unboundid.ldap.sdk.unboundidds.controls.InteractiveTransactionSpecificationResponseControl.get(searchResult);
                if ((txnResult != null) && (!txnResult.transactionValid())) {
                    sourceTxnID = null;
                }
            } catch (final LDAPException le) {
                Debug.debugException(le);
            }
            if (!searchListener.targetTransactionValid()) {
                targetTxnID = null;
            }
            break processingBlock;
        }
        // If an error occurred during add processing, then fail.
        if (resultCode.get() == null) {
            targetServerAltered = true;
        } else {
            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 ArrayList<Control> deleteControlList = new ArrayList<>(4);
        deleteControlList.add(sourceTxnControl);
        deleteControlList.add(new ManageDsaITRequestControl(true));
        if (opPurposeControl != null) {
            deleteControlList.add(opPurposeControl);
        }
        if (suppressRefInt) {
            deleteControlList.add(new SuppressReferentialIntegrityUpdatesRequestControl(false));
        }
        final Control[] deleteControls = new Control[deleteControlList.size()];
        deleteControlList.toArray(deleteControls);
        for (final DN dn : sourceEntryDNs) {
            if (listener != null) {
                try {
                    listener.doPreDeleteProcessing(dn);
                } catch (final Exception e) {
                    Debug.debugException(e);
                    resultCode.compareAndSet(null, ResultCode.LOCAL_ERROR);
                    append(ERR_MOVE_SUBTREE_PRE_DELETE_FAILURE.get(dn.toString(), StaticUtils.getExceptionMessage(e)), errorMsg);
                    break processingBlock;
                }
            }
            LDAPResult deleteResult;
            try {
                deleteResult = sourceConnection.delete(new DeleteRequest(dn, deleteControls));
            } catch (final LDAPException le) {
                Debug.debugException(le);
                deleteResult = le.toLDAPResult();
            }
            if (deleteResult.getResultCode() == ResultCode.SUCCESS) {
                sourceServerAltered = true;
                entriesDeletedFromSource.incrementAndGet();
                try {
                    final com.unboundid.ldap.sdk.unboundidds.controls.InteractiveTransactionSpecificationResponseControl txnResult = com.unboundid.ldap.sdk.unboundidds.controls.InteractiveTransactionSpecificationResponseControl.get(deleteResult);
                    if ((txnResult == null) || (!txnResult.transactionValid())) {
                        resultCode.compareAndSet(null, ResultCode.LOCAL_ERROR);
                        append(ERR_MOVE_ENTRY_DELETE_TXN_NO_LONGER_VALID.get(dn.toString()), errorMsg);
                        break processingBlock;
                    }
                } catch (final LDAPException le) {
                    Debug.debugException(le);
                    resultCode.compareAndSet(null, le.getResultCode());
                    append(ERR_MOVE_ENTRY_CANNOT_DECODE_DELETE_TXN_CONTROL.get(dn.toString(), StaticUtils.getExceptionMessage(le)), errorMsg);
                    break processingBlock;
                }
            } else {
                resultCode.compareAndSet(null, deleteResult.getResultCode());
                append(ERR_MOVE_SUBTREE_DELETE_FAILURE.get(dn.toString(), deleteResult.getDiagnosticMessage()), errorMsg);
                try {
                    final com.unboundid.ldap.sdk.unboundidds.controls.InteractiveTransactionSpecificationResponseControl txnResult = com.unboundid.ldap.sdk.unboundidds.controls.InteractiveTransactionSpecificationResponseControl.get(deleteResult);
                    if ((txnResult != null) && (!txnResult.transactionValid())) {
                        sourceTxnID = null;
                    }
                } catch (final LDAPException le) {
                    Debug.debugException(le);
                }
                break processingBlock;
            }
            if (listener != null) {
                try {
                    listener.doPostDeleteProcessing(dn);
                } catch (final Exception e) {
                    Debug.debugException(e);
                    resultCode.compareAndSet(null, ResultCode.LOCAL_ERROR);
                    append(ERR_MOVE_SUBTREE_POST_DELETE_FAILURE.get(dn.toString(), StaticUtils.getExceptionMessage(e)), errorMsg);
                    break processingBlock;
                }
            }
        }
        // Commit the transaction in the target server.
        try {
            final com.unboundid.ldap.sdk.unboundidds.extensions.EndInteractiveTransactionExtendedRequest commitRequest;
            if (opPurposeControl == null) {
                commitRequest = new com.unboundid.ldap.sdk.unboundidds.extensions.EndInteractiveTransactionExtendedRequest(targetTxnID, true);
            } else {
                commitRequest = new com.unboundid.ldap.sdk.unboundidds.extensions.EndInteractiveTransactionExtendedRequest(targetTxnID, true, new Control[] { opPurposeControl });
            }
            final ExtendedResult commitResult = targetConnection.processExtendedOperation(commitRequest);
            if (commitResult.getResultCode() == ResultCode.SUCCESS) {
                targetTxnID = null;
            } else {
                resultCode.compareAndSet(null, commitResult.getResultCode());
                append(ERR_MOVE_ENTRY_CANNOT_COMMIT_TARGET_TXN.get(commitResult.getDiagnosticMessage()), errorMsg);
                break processingBlock;
            }
        } catch (final LDAPException le) {
            Debug.debugException(le);
            resultCode.compareAndSet(null, le.getResultCode());
            append(ERR_MOVE_ENTRY_CANNOT_COMMIT_TARGET_TXN.get(StaticUtils.getExceptionMessage(le)), errorMsg);
            break processingBlock;
        }
        // Commit the transaction in the source server.
        try {
            final com.unboundid.ldap.sdk.unboundidds.extensions.EndInteractiveTransactionExtendedRequest commitRequest;
            if (opPurposeControl == null) {
                commitRequest = new com.unboundid.ldap.sdk.unboundidds.extensions.EndInteractiveTransactionExtendedRequest(sourceTxnID, true);
            } else {
                commitRequest = new com.unboundid.ldap.sdk.unboundidds.extensions.EndInteractiveTransactionExtendedRequest(sourceTxnID, true, new Control[] { opPurposeControl });
            }
            final ExtendedResult commitResult = sourceConnection.processExtendedOperation(commitRequest);
            if (commitResult.getResultCode() == ResultCode.SUCCESS) {
                sourceTxnID = null;
            } else {
                resultCode.compareAndSet(null, commitResult.getResultCode());
                append(ERR_MOVE_ENTRY_CANNOT_COMMIT_SOURCE_TXN.get(commitResult.getDiagnosticMessage()), errorMsg);
                break processingBlock;
            }
        } catch (final LDAPException le) {
            Debug.debugException(le);
            resultCode.compareAndSet(null, le.getResultCode());
            append(ERR_MOVE_ENTRY_CANNOT_COMMIT_SOURCE_TXN.get(StaticUtils.getExceptionMessage(le)), errorMsg);
            append(ERR_MOVE_ENTRY_EXISTS_IN_BOTH_SERVERS.get(entryDN), adminMsg);
            break processingBlock;
        }
    } finally {
        // If the transaction is still active in the target server, then abort it.
        if (targetTxnID != null) {
            try {
                final com.unboundid.ldap.sdk.unboundidds.extensions.EndInteractiveTransactionExtendedRequest abortRequest;
                if (opPurposeControl == null) {
                    abortRequest = new com.unboundid.ldap.sdk.unboundidds.extensions.EndInteractiveTransactionExtendedRequest(targetTxnID, false);
                } else {
                    abortRequest = new com.unboundid.ldap.sdk.unboundidds.extensions.EndInteractiveTransactionExtendedRequest(targetTxnID, false, new Control[] { opPurposeControl });
                }
                final ExtendedResult abortResult = targetConnection.processExtendedOperation(abortRequest);
                if (abortResult.getResultCode() == ResultCode.INTERACTIVE_TRANSACTION_ABORTED) {
                    targetServerAltered = false;
                    entriesAddedToTarget.set(0);
                    append(INFO_MOVE_ENTRY_TARGET_ABORT_SUCCEEDED.get(), errorMsg);
                } else {
                    append(ERR_MOVE_ENTRY_TARGET_ABORT_FAILURE.get(abortResult.getDiagnosticMessage()), errorMsg);
                    append(ERR_MOVE_ENTRY_TARGET_ABORT_FAILURE_ADMIN_ACTION.get(entryDN), adminMsg);
                }
            } catch (final Exception e) {
                Debug.debugException(e);
                append(ERR_MOVE_ENTRY_TARGET_ABORT_FAILURE.get(StaticUtils.getExceptionMessage(e)), errorMsg);
                append(ERR_MOVE_ENTRY_TARGET_ABORT_FAILURE_ADMIN_ACTION.get(entryDN), adminMsg);
            }
        }
        // If the transaction is still active in the source server, then abort it.
        if (sourceTxnID != null) {
            try {
                final com.unboundid.ldap.sdk.unboundidds.extensions.EndInteractiveTransactionExtendedRequest abortRequest;
                if (opPurposeControl == null) {
                    abortRequest = new com.unboundid.ldap.sdk.unboundidds.extensions.EndInteractiveTransactionExtendedRequest(sourceTxnID, false);
                } else {
                    abortRequest = new com.unboundid.ldap.sdk.unboundidds.extensions.EndInteractiveTransactionExtendedRequest(sourceTxnID, false, new Control[] { opPurposeControl });
                }
                final ExtendedResult abortResult = sourceConnection.processExtendedOperation(abortRequest);
                if (abortResult.getResultCode() == ResultCode.INTERACTIVE_TRANSACTION_ABORTED) {
                    sourceServerAltered = false;
                    entriesDeletedFromSource.set(0);
                    append(INFO_MOVE_ENTRY_SOURCE_ABORT_SUCCEEDED.get(), errorMsg);
                } else {
                    append(ERR_MOVE_ENTRY_SOURCE_ABORT_FAILURE.get(abortResult.getDiagnosticMessage()), errorMsg);
                    append(ERR_MOVE_ENTRY_SOURCE_ABORT_FAILURE_ADMIN_ACTION.get(entryDN), adminMsg);
                }
            } catch (final Exception e) {
                Debug.debugException(e);
                append(ERR_MOVE_ENTRY_SOURCE_ABORT_FAILURE.get(StaticUtils.getExceptionMessage(e)), errorMsg);
                append(ERR_MOVE_ENTRY_SOURCE_ABORT_FAILURE_ADMIN_ACTION.get(entryDN), 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 : ASN1OctetString(com.unboundid.asn1.ASN1OctetString) SearchRequest(com.unboundid.ldap.sdk.SearchRequest) ArrayList(java.util.ArrayList) 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) SuppressReferentialIntegrityUpdatesRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.SuppressReferentialIntegrityUpdatesRequestControl) LDAPResult(com.unboundid.ldap.sdk.LDAPResult) 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) LDAPSearchException(com.unboundid.ldap.sdk.LDAPSearchException) ArgumentException(com.unboundid.util.args.ArgumentException) LDAPException(com.unboundid.ldap.sdk.LDAPException) LDAPException(com.unboundid.ldap.sdk.LDAPException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) WhoAmIExtendedResult(com.unboundid.ldap.sdk.extensions.WhoAmIExtendedResult) ExtendedResult(com.unboundid.ldap.sdk.ExtendedResult) GetSubtreeAccessibilityExtendedResult(com.unboundid.ldap.sdk.unboundidds.extensions.GetSubtreeAccessibilityExtendedResult) DeleteRequest(com.unboundid.ldap.sdk.DeleteRequest) ResultCode(com.unboundid.ldap.sdk.ResultCode) NotNull(com.unboundid.util.NotNull)

Aggregations

Control (com.unboundid.ldap.sdk.Control)4 DraftLDUPSubentriesRequestControl (com.unboundid.ldap.sdk.controls.DraftLDUPSubentriesRequestControl)4 ManageDsaITRequestControl (com.unboundid.ldap.sdk.controls.ManageDsaITRequestControl)4 ReturnConflictEntriesRequestControl (com.unboundid.ldap.sdk.unboundidds.controls.ReturnConflictEntriesRequestControl)4 SoftDeletedEntryAccessRequestControl (com.unboundid.ldap.sdk.unboundidds.controls.SoftDeletedEntryAccessRequestControl)4 ASN1OctetString (com.unboundid.asn1.ASN1OctetString)3 DN (com.unboundid.ldap.sdk.DN)3 OperationPurposeRequestControl (com.unboundid.ldap.sdk.unboundidds.controls.OperationPurposeRequestControl)3 RealAttributesOnlyRequestControl (com.unboundid.ldap.sdk.unboundidds.controls.RealAttributesOnlyRequestControl)3 NotNull (com.unboundid.util.NotNull)3 ArrayList (java.util.ArrayList)3 AtomicReference (java.util.concurrent.atomic.AtomicReference)3 LDAPException (com.unboundid.ldap.sdk.LDAPException)2 LDAPSearchException (com.unboundid.ldap.sdk.LDAPSearchException)2 ResultCode (com.unboundid.ldap.sdk.ResultCode)2 SearchRequest (com.unboundid.ldap.sdk.SearchRequest)2 SearchResult (com.unboundid.ldap.sdk.SearchResult)2 SimplePagedResultsControl (com.unboundid.ldap.sdk.controls.SimplePagedResultsControl)2 PermitUnindexedSearchRequestControl (com.unboundid.ldap.sdk.unboundidds.controls.PermitUnindexedSearchRequestControl)2 SuppressReferentialIntegrityUpdatesRequestControl (com.unboundid.ldap.sdk.unboundidds.controls.SuppressReferentialIntegrityUpdatesRequestControl)2