parentBackendEntry.getObjectClasses(),
parentBackendEntry.getUserAttributes(),
parentBackendEntry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
Backend parentBackend = DirectoryServer.getBackend(parentBackendID);
assertNotNull(parentBackend);
assertEquals(parentBackend,
DirectoryServer.getBackendWithBaseDN(parentBaseDN));
assertNull(parentBackend.getParentBackend());
assertTrue(parentBackend.getSubordinateBackends().length == 0);
assertFalse(parentBackend.entryExists(parentBaseDN));
Entry e = createEntry(parentBaseDN);
addOperation = conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(),
e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertTrue(parentBackend.entryExists(parentBaseDN));
assertTrue(DirectoryServer.isNamingContext(parentBaseDN));
// Add the grandchild backend to the server.
DN grandchildBaseDN = DN.decode("ou=grandchild,ou=child,o=parent");
String grandchildBackendID = createBackendID(grandchildBaseDN);
Entry grandchildBackendEntry = createBackendEntry(grandchildBackendID, true,
grandchildBaseDN);
addOperation =
conn.processAdd(grandchildBackendEntry.getDN(),
grandchildBackendEntry.getObjectClasses(),
grandchildBackendEntry.getUserAttributes(),
grandchildBackendEntry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
Backend grandchildBackend = DirectoryServer.getBackend(grandchildBackendID);
assertNotNull(grandchildBackend);
assertEquals(grandchildBackend,
DirectoryServer.getBackendWithBaseDN(grandchildBaseDN));
assertNotNull(grandchildBackend.getParentBackend());
assertEquals(grandchildBackend.getParentBackend(), parentBackend);
assertTrue(parentBackend.getSubordinateBackends().length == 1);
assertFalse(grandchildBackend.entryExists(grandchildBaseDN));
// Verify that we can't create the grandchild base entry because its parent
// doesn't exist.
e = createEntry(grandchildBaseDN);
addOperation = conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(),
e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.NO_SUCH_OBJECT);
assertFalse(grandchildBackend.entryExists(grandchildBaseDN));
// Add the child backend to the server and create its base entry.
DN childBaseDN = DN.decode("ou=child,o=parent");
String childBackendID = createBackendID(childBaseDN);
Entry childBackendEntry = createBackendEntry(childBackendID, true,
childBaseDN);
addOperation =
conn.processAdd(childBackendEntry.getDN(),
childBackendEntry.getObjectClasses(),
childBackendEntry.getUserAttributes(),
childBackendEntry.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
Backend childBackend = DirectoryServer.getBackend(childBackendID);
assertNotNull(childBackend);
assertEquals(childBackend,
DirectoryServer.getBackendWithBaseDN(childBaseDN));
assertNotNull(childBackend.getParentBackend());
assertEquals(parentBackend, childBackend.getParentBackend());
assertTrue(parentBackend.getSubordinateBackends().length == 1);
assertFalse(childBackend.entryExists(childBaseDN));
assertTrue(childBackend.getSubordinateBackends().length == 1);
assertEquals(childBackend.getSubordinateBackends()[0], grandchildBackend);
assertEquals(grandchildBackend.getParentBackend(), childBackend);
e = createEntry(childBaseDN);
addOperation = conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(),
e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertTrue(childBackend.entryExists(childBaseDN));
// Now we can create the grandchild base entry.
e = createEntry(grandchildBaseDN);
addOperation = conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(),
e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertTrue(grandchildBackend.entryExists(grandchildBaseDN));
// Verify that a subtree search can see all three entries.
InternalSearchOperation internalSearch =
conn.processSearch(parentBaseDN, SearchScope.WHOLE_SUBTREE,
SearchFilter.createFilterFromString("(objectClass=*)"));
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
assertEquals(internalSearch.getSearchEntries().size(), 3);
// Disable the intermediate (child) backend. This should be allowed.
ArrayList<Modification> mods = new ArrayList<Modification>();
mods.add(new Modification(ModificationType.REPLACE,
Attributes.create("ds-cfg-enabled",
"false")));
ModifyOperation modifyOperation =
conn.processModify(childBackendEntry.getDN(), mods);
assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
// Make sure that we now only see two entries with the subtree search
// (and those two entries should be the parent and grandchild base entries).
internalSearch =
conn.processSearch(parentBaseDN, SearchScope.WHOLE_SUBTREE,
SearchFilter.createFilterFromString("(objectClass=*)"));
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
assertEquals(internalSearch.getSearchEntries().size(), 2);
// Re-enable the intermediate backend.
mods = new ArrayList<Modification>();
mods.add(new Modification(ModificationType.REPLACE,
Attributes.create("ds-cfg-enabled", "true")));
modifyOperation = conn.processModify(childBackendEntry.getDN(), mods);
assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
// Update our reference to the child backend since the old one is no longer
// valid, and make sure that it got re-inserted back into the same place in
// the hierarchy.
childBackend = DirectoryServer.getBackend(childBackendID);
assertNotNull(childBackend);
assertEquals(childBackend,
DirectoryServer.getBackendWithBaseDN(childBaseDN));
assertNotNull(childBackend.getParentBackend());
assertEquals(parentBackend, childBackend.getParentBackend());
assertTrue(parentBackend.getSubordinateBackends().length == 1);
assertFalse(childBackend.entryExists(childBaseDN));
assertTrue(childBackend.getSubordinateBackends().length == 1);
assertEquals(childBackend.getSubordinateBackends()[0], grandchildBackend);
assertEquals(grandchildBackend.getParentBackend(), childBackend);
// Since the memory backend that we're using for this test doesn't retain
// entries across stops and restarts, a subtree search below the parent
// should still only return two entries, which means that it's going through
// the entire chain of backends.
internalSearch =
conn.processSearch(parentBaseDN, SearchScope.WHOLE_SUBTREE,
SearchFilter.createFilterFromString("(objectClass=*)"));
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
assertEquals(internalSearch.getSearchEntries().size(), 2);
// Add the child entry back into the server to get things back to the way
// they were before we disabled the backend.
e = createEntry(childBaseDN);
addOperation = conn.processAdd(e.getDN(), e.getObjectClasses(),
e.getUserAttributes(),
e.getOperationalAttributes());
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
assertTrue(childBackend.entryExists(childBaseDN));
// We should again be able to see all three entries when performing a
// search.
internalSearch =
conn.processSearch(parentBaseDN, SearchScope.WHOLE_SUBTREE,
SearchFilter.createFilterFromString("(objectClass=*)"));
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
assertEquals(internalSearch.getSearchEntries().size(), 3);
// Get rid of the entries in the proper order.
DeleteOperation deleteOperation =
conn.processDelete(grandchildBackendEntry.getDN());
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
assertNull(DirectoryServer.getBackend(grandchildBackendID));
assertTrue(childBackend.getSubordinateBackends().length == 0);
assertTrue(parentBackend.getSubordinateBackends().length == 1);
deleteOperation = conn.processDelete(childBackendEntry.getDN());
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
assertNull(DirectoryServer.getBackend(childBackendID));