use of com.unboundid.ldap.sdk.unboundidds.controls.OperationPurposeRequestControl in project ldapsdk by pingidentity.
the class MoveSubtreeTestCase method testFailedTransactionMoveBaseDNMissing.
/**
* Tests the move subtree method call with a move that fails because the
* specified subtree does not exist.
* <BR><BR>
* Access to two UnboundID Directory Server instances are required for
* complete testing.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
@SuppressWarnings("deprecation")
public void testFailedTransactionMoveBaseDNMissing() throws Exception {
if (!isSecondDirectoryInstanceAvailable()) {
return;
}
final LDAPConnection sourceConn = getAdminConnection();
final LDAPConnection targetConn = getSecondAdminConnection();
if (!serversSupportInteractiveTransactions(sourceConn, targetConn)) {
sourceConn.close();
targetConn.close();
return;
}
try {
sourceConn.add(getTestBaseDN(), getBaseEntryAttributes());
targetConn.add(getTestBaseDN(), getBaseEntryAttributes());
final OperationPurposeRequestControl opPurpose = new OperationPurposeRequestControl("move-subtree-test", "1.0", 10, "testSuccessfulMove");
final MoveSubtreeResult result = MoveSubtree.moveEntryWithInteractiveTransaction(sourceConn, targetConn, "ou=missing," + getTestBaseDN(), opPurpose, null);
assertFalse(result.getResultCode() == ResultCode.SUCCESS);
assertNotNull(result.getErrorMessage());
assertFalse(result.sourceServerAltered());
assertFalse(result.targetServerAltered());
} finally {
subtreeDelete(sourceConn);
sourceConn.close();
subtreeDelete(targetConn);
targetConn.close();
}
}
use of com.unboundid.ldap.sdk.unboundidds.controls.OperationPurposeRequestControl in project ldapsdk by pingidentity.
the class LDAPDelete method getSearchControls.
/**
* Retrieves the set of controls that should be included in search requests.
*
* @return The set of controls that should be included in delete requests.
*/
@NotNull()
private List<Control> getSearchControls() {
final List<Control> controlList = new ArrayList<>(10);
controlList.addAll(routeToBackendSetRequestControls);
if (manageDsaIT.isPresent()) {
controlList.add(new ManageDsaITRequestControl(true));
}
if (proxyV1As.isPresent()) {
controlList.add(new ProxiedAuthorizationV1RequestControl(proxyV1As.getValue().toString()));
}
if (proxyAs.isPresent()) {
controlList.add(new ProxiedAuthorizationV2RequestControl(proxyAs.getValue()));
}
if (operationPurpose.isPresent()) {
controlList.add(new OperationPurposeRequestControl(true, "ldapdelete", Version.NUMERIC_VERSION_STRING, LDAPDelete.class.getName() + ".getSearchControls", operationPurpose.getValue()));
}
if (routeToServer.isPresent()) {
controlList.add(new RouteToServerRequestControl(true, routeToServer.getValue(), false, false, false));
}
return Collections.unmodifiableList(controlList);
}
use of com.unboundid.ldap.sdk.unboundidds.controls.OperationPurposeRequestControl in project ldapsdk by pingidentity.
the class MoveSubtreeTestCase method testSuccessfulAccessibilityMoveWithMethod.
/**
* Tests the move subtree method call with a successful simple move.
* <BR><BR>
* Access to two UnboundID Directory Server instances are required for
* complete testing.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testSuccessfulAccessibilityMoveWithMethod() throws Exception {
if (!isSecondDirectoryInstanceAvailable()) {
return;
}
final LDAPConnection sourceConn = getAdminConnection();
final LDAPConnection targetConn = getSecondAdminConnection();
try {
sourceConn.add(getTestBaseDN(), getBaseEntryAttributes());
targetConn.add(getTestBaseDN(), getBaseEntryAttributes());
sourceConn.add("dn: ou=branch," + getTestBaseDN(), "objectClass: top", "objectClass: organizationalUnit", "ou: branch");
for (int i = 1; i <= 10; i++) {
sourceConn.add("dn: ou=sub" + i + ",ou=branch," + getTestBaseDN(), "objectClass: top", "objectClass: organizationalUnit", "ou: sub" + i);
}
MoveSubtreeResult result = MoveSubtree.moveSubtreeWithRestrictedAccessibility(sourceConn, targetConn, "ou=branch," + getTestBaseDN(), 50, null, null);
assertEquals(result.getResultCode(), ResultCode.SUCCESS);
assertNull(result.getErrorMessage());
assertNull(result.getAdminActionRequired());
assertTrue(result.sourceServerAltered());
assertTrue(result.targetServerAltered());
assertEquals(result.getEntriesReadFromSource(), 11);
assertEquals(result.getEntriesAddedToTarget(), 11);
assertEquals(result.getEntriesDeletedFromSource(), 11);
assertEntryMissing(sourceConn, "ou=branch," + getTestBaseDN());
assertEntryExists(targetConn, "ou=branch," + getTestBaseDN());
assertEntryExists(targetConn, "ou=sub1,ou=branch," + getTestBaseDN());
final OperationPurposeRequestControl opPurpose = new OperationPurposeRequestControl("move-subtree-test", "1.0", 10, "testSuccessfulMove");
final TestMoveSubtreeListener listener = new TestMoveSubtreeListener();
result = MoveSubtree.moveSubtreeWithRestrictedAccessibility(targetConn, sourceConn, "ou=branch," + getTestBaseDN(), 50, opPurpose, listener);
assertEquals(result.getResultCode(), ResultCode.SUCCESS);
assertNull(result.getErrorMessage());
assertNull(result.getAdminActionRequired());
assertTrue(result.sourceServerAltered());
assertTrue(result.targetServerAltered());
assertEquals(result.getEntriesReadFromSource(), 11);
assertEquals(result.getEntriesAddedToTarget(), 11);
assertEquals(result.getEntriesDeletedFromSource(), 11);
assertTrue(listener.preAddCalled());
assertTrue(listener.postAddCalled());
assertTrue(listener.preDeleteCalled());
assertTrue(listener.postDeleteCalled());
assertEntryExists(sourceConn, "ou=branch," + getTestBaseDN());
assertEntryExists(sourceConn, "ou=sub1,ou=branch," + getTestBaseDN());
assertEntryMissing(targetConn, "ou=branch," + getTestBaseDN());
new MoveSubtree(null, null).handleUnsolicitedNotification(sourceConn, new NoticeOfDisconnectionExtendedResult(1, ResultCode.OTHER, "test", null, null, null));
} finally {
subtreeDelete(sourceConn);
sourceConn.close();
subtreeDelete(targetConn);
targetConn.close();
}
}
use of com.unboundid.ldap.sdk.unboundidds.controls.OperationPurposeRequestControl in project ldapsdk by pingidentity.
the class MoveSubtree method checkInitialAccessibility.
/**
* Ensures that the specified subtree is accessible in both the source and
* target servers. If it is not accessible, then it may indicate that another
* administrative operation is in progress for the subtree, or that a previous
* move-subtree operation was interrupted before it could complete.
*
* @param sourceConnection The connection to use to communicate with the
* source directory server.
* @param targetConnection The connection to use to communicate with the
* target directory server.
* @param baseDN The base DN for which to verify accessibility.
* @param opPurposeControl An optional operation purpose request control
* that may be included in the requests.
*
* @return {@code null} if the specified subtree is accessible in both the
* source and target servers, or a non-{@code null} object with the
* result that should be used if there is an accessibility problem
* with the subtree on the source and/or target server.
*/
@Nullable()
private static MoveSubtreeResult checkInitialAccessibility(@NotNull final LDAPConnection sourceConnection, @NotNull final LDAPConnection targetConnection, @NotNull final String baseDN, @Nullable final OperationPurposeRequestControl opPurposeControl) {
final DN parsedBaseDN;
try {
parsedBaseDN = new DN(baseDN);
} catch (final Exception e) {
Debug.debugException(e);
return new MoveSubtreeResult(ResultCode.INVALID_DN_SYNTAX, ERR_MOVE_SUBTREE_CANNOT_PARSE_BASE_DN.get(baseDN, StaticUtils.getExceptionMessage(e)), null, false, false, 0, 0, 0);
}
final Control[] controls;
if (opPurposeControl == null) {
controls = StaticUtils.NO_CONTROLS;
} else {
controls = new Control[] { opPurposeControl };
}
// Get the restrictions from the source server. If there are any, then
// make sure that nothing in the hierarchy of the base DN is non-accessible.
final GetSubtreeAccessibilityExtendedResult sourceResult;
try {
sourceResult = (GetSubtreeAccessibilityExtendedResult) sourceConnection.processExtendedOperation(new GetSubtreeAccessibilityExtendedRequest(controls));
if (sourceResult.getResultCode() != ResultCode.SUCCESS) {
throw new LDAPException(sourceResult);
}
} catch (final LDAPException le) {
Debug.debugException(le);
return new MoveSubtreeResult(le.getResultCode(), ERR_MOVE_SUBTREE_CANNOT_GET_ACCESSIBILITY_STATE.get(baseDN, INFO_MOVE_SUBTREE_CONNECTION_NAME_SOURCE.get(), le.getMessage()), null, false, false, 0, 0, 0);
}
boolean sourceMatch = false;
String sourceMessage = null;
SubtreeAccessibilityRestriction sourceRestriction = null;
final List<SubtreeAccessibilityRestriction> sourceRestrictions = sourceResult.getAccessibilityRestrictions();
if (sourceRestrictions != null) {
for (final SubtreeAccessibilityRestriction r : sourceRestrictions) {
if (r.getAccessibilityState() == SubtreeAccessibilityState.ACCESSIBLE) {
continue;
}
final DN restrictionDN;
try {
restrictionDN = new DN(r.getSubtreeBaseDN());
} catch (final Exception e) {
Debug.debugException(e);
return new MoveSubtreeResult(ResultCode.INVALID_DN_SYNTAX, ERR_MOVE_SUBTREE_CANNOT_PARSE_RESTRICTION_BASE_DN.get(r.getSubtreeBaseDN(), INFO_MOVE_SUBTREE_CONNECTION_NAME_SOURCE.get(), r.toString(), StaticUtils.getExceptionMessage(e)), null, false, false, 0, 0, 0);
}
if (restrictionDN.equals(parsedBaseDN)) {
sourceMatch = true;
sourceRestriction = r;
sourceMessage = ERR_MOVE_SUBTREE_NOT_ACCESSIBLE.get(baseDN, INFO_MOVE_SUBTREE_CONNECTION_NAME_SOURCE.get(), r.getAccessibilityState().getStateName());
break;
} else if (restrictionDN.isAncestorOf(parsedBaseDN, false)) {
sourceRestriction = r;
sourceMessage = ERR_MOVE_SUBTREE_WITHIN_UNACCESSIBLE_TREE.get(baseDN, INFO_MOVE_SUBTREE_CONNECTION_NAME_SOURCE.get(), r.getSubtreeBaseDN(), r.getAccessibilityState().getStateName());
break;
} else if (restrictionDN.isDescendantOf(parsedBaseDN, false)) {
sourceRestriction = r;
sourceMessage = ERR_MOVE_SUBTREE_CONTAINS_UNACCESSIBLE_TREE.get(baseDN, INFO_MOVE_SUBTREE_CONNECTION_NAME_SOURCE.get(), r.getSubtreeBaseDN(), r.getAccessibilityState().getStateName());
break;
}
}
}
// Get the restrictions from the target server. If there are any, then
// make sure that nothing in the hierarchy of the base DN is non-accessible.
final GetSubtreeAccessibilityExtendedResult targetResult;
try {
targetResult = (GetSubtreeAccessibilityExtendedResult) targetConnection.processExtendedOperation(new GetSubtreeAccessibilityExtendedRequest(controls));
if (targetResult.getResultCode() != ResultCode.SUCCESS) {
throw new LDAPException(targetResult);
}
} catch (final LDAPException le) {
Debug.debugException(le);
return new MoveSubtreeResult(le.getResultCode(), ERR_MOVE_SUBTREE_CANNOT_GET_ACCESSIBILITY_STATE.get(baseDN, INFO_MOVE_SUBTREE_CONNECTION_NAME_TARGET.get(), le.getMessage()), null, false, false, 0, 0, 0);
}
boolean targetMatch = false;
String targetMessage = null;
SubtreeAccessibilityRestriction targetRestriction = null;
final List<SubtreeAccessibilityRestriction> targetRestrictions = targetResult.getAccessibilityRestrictions();
if (targetRestrictions != null) {
for (final SubtreeAccessibilityRestriction r : targetRestrictions) {
if (r.getAccessibilityState() == SubtreeAccessibilityState.ACCESSIBLE) {
continue;
}
final DN restrictionDN;
try {
restrictionDN = new DN(r.getSubtreeBaseDN());
} catch (final Exception e) {
Debug.debugException(e);
return new MoveSubtreeResult(ResultCode.INVALID_DN_SYNTAX, ERR_MOVE_SUBTREE_CANNOT_PARSE_RESTRICTION_BASE_DN.get(r.getSubtreeBaseDN(), INFO_MOVE_SUBTREE_CONNECTION_NAME_TARGET.get(), r.toString(), StaticUtils.getExceptionMessage(e)), null, false, false, 0, 0, 0);
}
if (restrictionDN.equals(parsedBaseDN)) {
targetMatch = true;
targetRestriction = r;
targetMessage = ERR_MOVE_SUBTREE_NOT_ACCESSIBLE.get(baseDN, INFO_MOVE_SUBTREE_CONNECTION_NAME_TARGET.get(), r.getAccessibilityState().getStateName());
break;
} else if (restrictionDN.isAncestorOf(parsedBaseDN, false)) {
targetRestriction = r;
targetMessage = ERR_MOVE_SUBTREE_WITHIN_UNACCESSIBLE_TREE.get(baseDN, INFO_MOVE_SUBTREE_CONNECTION_NAME_TARGET.get(), r.getSubtreeBaseDN(), r.getAccessibilityState().getStateName());
break;
} else if (restrictionDN.isDescendantOf(parsedBaseDN, false)) {
targetRestriction = r;
targetMessage = ERR_MOVE_SUBTREE_CONTAINS_UNACCESSIBLE_TREE.get(baseDN, INFO_MOVE_SUBTREE_CONNECTION_NAME_TARGET.get(), r.getSubtreeBaseDN(), r.getAccessibilityState().getStateName());
break;
}
}
}
// to do anything else.
if ((sourceRestriction == null) && (targetRestriction == null)) {
return null;
}
// specific advice about how to recover.
if (sourceMatch || targetMatch) {
// accessible before running again.
if ((sourceRestriction != null) && sourceRestriction.getAccessibilityState().isReadOnly() && (targetRestriction != null) && targetRestriction.getAccessibilityState().isHidden()) {
return new MoveSubtreeResult(ResultCode.UNWILLING_TO_PERFORM, ERR_MOVE_SUBTREE_POSSIBLY_INTERRUPTED_IN_ADDS.get(baseDN, sourceConnection.getConnectedAddress(), sourceConnection.getConnectedPort(), targetConnection.getConnectedAddress(), targetConnection.getConnectedPort()), ERR_MOVE_SUBTREE_POSSIBLY_INTERRUPTED_IN_ADDS_ADMIN_MSG.get(), false, false, 0, 0, 0);
}
// subtree accessible. There shouldn't be a need to run again.
if ((sourceRestriction != null) && sourceRestriction.getAccessibilityState().isHidden() && (targetRestriction == null)) {
return new MoveSubtreeResult(ResultCode.UNWILLING_TO_PERFORM, ERR_MOVE_SUBTREE_POSSIBLY_INTERRUPTED_IN_DELETES.get(baseDN, sourceConnection.getConnectedAddress(), sourceConnection.getConnectedPort(), targetConnection.getConnectedAddress(), targetConnection.getConnectedPort()), ERR_MOVE_SUBTREE_POSSIBLY_INTERRUPTED_IN_DELETES_ADMIN_MSG.get(), false, false, 0, 0, 0);
}
}
// If we've made it here, then we're in a situation we don't recognize.
// Provide general information about the current state of the subtree and
// recommend that the user contact support if they need assistance.
final StringBuilder details = new StringBuilder();
if (sourceMessage != null) {
details.append(sourceMessage);
}
if (targetMessage != null) {
append(targetMessage, details);
}
return new MoveSubtreeResult(ResultCode.UNWILLING_TO_PERFORM, ERR_MOVE_SUBTREE_POSSIBLY_INTERRUPTED.get(baseDN, sourceConnection.getConnectedAddress(), sourceConnection.getConnectedPort(), targetConnection.getConnectedAddress(), targetConnection.getConnectedPort(), details.toString()), null, false, false, 0, 0, 0);
}
use of com.unboundid.ldap.sdk.unboundidds.controls.OperationPurposeRequestControl in project ldapsdk by pingidentity.
the class MoveSubtree method deleteEntries.
/**
* Deletes a specified set of entries from the indicated server.
*
* @param connection The connection to use to communicate with the
* server.
* @param isSource Indicates whether the connection is to the source
* or target server.
* @param entryDNs The set of DNs of the entries to be deleted.
* @param opPurposeControl An optional operation purpose request control
* that may be included in the requests.
* @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.
* @param deleteCount A counter to increment for each delete operation
* processed.
* @param resultCode A reference to the result code to use for the
* move subtree operation.
* @param errorMsg A buffer to which any appropriate error messages
* may be appended.
*
* @return {@code true} if the delete was completely successful, or
* {@code false} if any errors were encountered.
*/
private static boolean deleteEntries(@NotNull final LDAPConnection connection, final boolean isSource, @NotNull final TreeSet<DN> entryDNs, @Nullable final OperationPurposeRequestControl opPurposeControl, final boolean suppressRefInt, @Nullable final MoveSubtreeListener listener, @NotNull final AtomicInteger deleteCount, @NotNull final AtomicReference<ResultCode> resultCode, @NotNull final StringBuilder errorMsg) {
final ArrayList<Control> deleteControlList = new ArrayList<>(3);
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);
boolean successful = true;
for (final DN dn : entryDNs) {
if (isSource && (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);
successful = false;
continue;
}
}
LDAPResult deleteResult;
try {
deleteResult = connection.delete(new DeleteRequest(dn, deleteControls));
} catch (final LDAPException le) {
Debug.debugException(le);
deleteResult = le.toLDAPResult();
}
if (deleteResult.getResultCode() == ResultCode.SUCCESS) {
deleteCount.incrementAndGet();
} else {
resultCode.compareAndSet(null, deleteResult.getResultCode());
append(ERR_MOVE_SUBTREE_DELETE_FAILURE.get(dn.toString(), deleteResult.getDiagnosticMessage()), errorMsg);
successful = false;
continue;
}
if (isSource && (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);
successful = false;
}
}
}
return successful;
}
Aggregations