From 9eb4e7cc27b14c99ac2ee9f3df672533959a95d9 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Wed, 14 Mar 2007 20:01:57 +0000
Subject: [PATCH] Update the schema and memory backends so that they will properly set the matched DN field in the response if the backend doesn't have the entry specified as the search base DN but does have an ancestor for that entry.

---
 opends/tests/unit-tests-testng/src/server/org/opends/server/core/SearchOperationTestCase.java   |   30 +++++++++++++++
 opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java |   27 +++++++++++++
 opends/src/server/org/opends/server/backends/SchemaBackend.java                                 |    9 ++++
 opends/src/server/org/opends/server/backends/MemoryBackend.java                                 |   34 ++++++++++++-----
 4 files changed, 89 insertions(+), 11 deletions(-)

diff --git a/opends/src/server/org/opends/server/backends/MemoryBackend.java b/opends/src/server/org/opends/server/backends/MemoryBackend.java
index 63eab74..07c7345 100644
--- a/opends/src/server/org/opends/server/backends/MemoryBackend.java
+++ b/opends/src/server/org/opends/server/backends/MemoryBackend.java
@@ -551,21 +551,35 @@
     SearchFilter filter = searchOperation.getFilter();
 
 
+    // Make sure the base entry exists if it's supposed to be in this backend.
+    Entry baseEntry = entryMap.get(baseDN);
+    if ((baseEntry == null) && handlesEntry(baseDN))
+    {
+      DN matchedDN = baseDN.getParentDNInSuffix();
+      while (matchedDN != null)
+      {
+        if (entryMap.containsKey(matchedDN))
+        {
+          break;
+        }
+
+        matchedDN = matchedDN.getParentDNInSuffix();
+      }
+
+      int    msgID   = MSGID_MEMORYBACKEND_ENTRY_DOESNT_EXIST;
+      String message = getMessage(msgID, String.valueOf(baseDN));
+      throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message, msgID,
+                                   matchedDN, null);
+    }
+
+
     // If it's a base-level search, then just get that entry and return it if it
     // matches the filter.
     if (scope == SearchScope.BASE_OBJECT)
     {
-      Entry entry = entryMap.get(baseDN);
-      if (entry == null)
+      if (filter.matchesEntry(baseEntry))
       {
-        int    msgID   = MSGID_MEMORYBACKEND_ENTRY_DOESNT_EXIST;
-        String message = getMessage(msgID, String.valueOf(baseDN));
-        throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message, msgID);
-      }
-
-      if (filter.matchesEntry(entry))
-      {
-        searchOperation.returnEntry(entry, new LinkedList<Control>());
+        searchOperation.returnEntry(baseEntry, new LinkedList<Control>());
       }
     }
     else
diff --git a/opends/src/server/org/opends/server/backends/SchemaBackend.java b/opends/src/server/org/opends/server/backends/SchemaBackend.java
index 7825ab9..7a8034f 100644
--- a/opends/src/server/org/opends/server/backends/SchemaBackend.java
+++ b/opends/src/server/org/opends/server/backends/SchemaBackend.java
@@ -4078,6 +4078,7 @@
 
     boolean found = false;
     DN[] dnArray = baseDNs;
+    DN matchedDN = null;
     for (DN dn : dnArray)
     {
       if (dn.equals(baseDN))
@@ -4085,6 +4086,11 @@
         found = true;
         break;
       }
+      else if (dn.isAncestorOf(baseDN))
+      {
+        matchedDN = dn;
+        break;
+      }
     }
 
     if (! found)
@@ -4093,7 +4099,8 @@
       String message = getMessage(msgID, searchOperation.getConnectionID(),
                                   searchOperation.getOperationID(),
                                   String.valueOf(baseDN));
-      throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message, msgID);
+      throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message, msgID,
+                                   matchedDN, null);
     }
 
 
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java
index 265f827..35f7e23 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java
@@ -429,6 +429,33 @@
 
 
   /**
+   * Performs a set of searches in the schema backend to ensure that they
+   * correctly set the matched DN in the response.
+   *
+   * @throws  Exception  If an unexpected problem occurs.
+   */
+  @Test()
+  public void testSearchMatchedDN()
+         throws Exception
+  {
+    InternalClientConnection conn =
+         InternalClientConnection.getRootConnection();
+    DN baseDN = DN.decode("o=bogus,cn=schema");
+    SearchFilter filter =
+         SearchFilter.createFilterFromString("(objectClass=*)");
+
+    for (SearchScope scope : SearchScope.values())
+    {
+      InternalSearchOperation searchOperation =
+           conn.processSearch(baseDN, scope, filter);
+      assertNotNull(searchOperation.getMatchedDN(),
+                    "No matched DN for scope " + scope);
+    }
+  }
+
+
+
+  /**
    * Tests the behavior of the schema backend with regard to the
    * ds-cfg-show-all-attributes configuration.
    *
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/core/SearchOperationTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/core/SearchOperationTestCase.java
index 17b3825..ce63a78 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/core/SearchOperationTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/core/SearchOperationTestCase.java
@@ -854,4 +854,34 @@
     List<String> referrals = references.get(0).getReferralURLs();
     assertEquals(referrals.size(), 2);
   }
+
+  @Test
+  public void testSearchInternalMatchedDN() throws Exception
+  {
+    InvocationCounterPlugin.resetAllCounters();
+
+    TestCaseUtils.initializeTestBackend(true);
+    InternalClientConnection conn =
+         InternalClientConnection.getRootConnection();
+
+    InternalSearchOperation searchOperation =
+         new InternalSearchOperation(
+              conn,
+              InternalClientConnection.nextOperationID(),
+              InternalClientConnection.nextMessageID(),
+              new ArrayList<Control>(),
+              new ASN1OctetString("ou=nonexistent,o=test"),
+              SearchScope.WHOLE_SUBTREE,
+              DereferencePolicy.NEVER_DEREF_ALIASES,
+              Integer.MAX_VALUE,
+              Integer.MAX_VALUE,
+              false,
+              LDAPFilter.decode("(objectclass=*)"),
+              null, null);
+
+    searchOperation.run();
+
+    assertEquals(searchOperation.getResultCode(), ResultCode.NO_SUCH_OBJECT);
+    assertNotNull(searchOperation.getMatchedDN());
+  }
 }

--
Gitblit v1.10.0