From 97723183ad624c289fc1a0993c23acd38adb138b Mon Sep 17 00:00:00 2001
From: Jean-Noël Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Tue, 02 Aug 2016 07:21:10 +0000
Subject: [PATCH] Partial OPENDJ-2625 Convert all code that uses JNDI to use the SDK instead

---
 opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/NodeRefresher.java     |  406 +++++++++++++++++++++++---------------------------
 opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/BrowserController.java |   53 ++----
 2 files changed, 205 insertions(+), 254 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/BrowserController.java b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/BrowserController.java
index 954b2f2..dabf811 100644
--- a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/BrowserController.java
+++ b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/BrowserController.java
@@ -16,6 +16,7 @@
  */
 package org.opends.guitools.controlpanel.browser;
 
+import static org.opends.admin.ads.util.ConnectionUtils.*;
 import static org.opends.server.util.ServerConstants.*;
 
 import java.awt.Font;
@@ -34,7 +35,6 @@
 import javax.naming.NameNotFoundException;
 import javax.naming.NamingException;
 import javax.naming.directory.SearchControls;
-import javax.naming.directory.SearchResult;
 import javax.naming.ldap.Control;
 import javax.naming.ldap.ManageReferralControl;
 import javax.naming.ldap.SortControl;
@@ -48,8 +48,8 @@
 import javax.swing.tree.TreeNode;
 import javax.swing.tree.TreePath;
 
+import org.forgerock.opendj.ldap.responses.SearchResultEntry;
 import org.opends.admin.ads.ADSContext;
-import org.opends.admin.ads.util.ConnectionUtils;
 import org.opends.admin.ads.util.ConnectionWrapper;
 import org.opends.guitools.controlpanel.datamodel.CustomSearchResult;
 import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
@@ -659,7 +659,7 @@
    * @param localEntry the local entry corresponding to the node.
    * @param recursive whether the refresh must be executed recursively or not.
    */
-  private void startRefreshNode(BasicNode node, SearchResult localEntry,
+  private void startRefreshNode(BasicNode node, SearchResultEntry localEntry,
       boolean recursive) {
     if (node == rootNode) {
       // For the root node, readBaseEntry is meaningless.
@@ -1306,7 +1306,7 @@
          If succeeds we will update the remote url.  Set it to null for
          the case when there was a referral and it has been deleted */
         node.setRemoteUrl((String)null);
-        SearchResult localEntry = task.getLocalEntry();
+        SearchResultEntry localEntry = task.getLocalEntry();
         nodeChanged = updateNodeRendering(node, localEntry);
       }
       else if (oldState == NodeRefresher.State.SOLVING_REFERRAL) {
@@ -1425,7 +1425,7 @@
     boolean doNotTrust = numSubordinateHacker.containsChildrenOf(parentUrl);
 
     // Walk through the entries
-    for (SearchResult entry : task.getChildEntries())
+    for (SearchResultEntry entry : task.getChildEntries())
     {
       BasicNode child;
 
@@ -1433,7 +1433,7 @@
       int index;
       if (differential) {
 //      System.out.println("Differential mode -> starting to search");
-        index = findChildNode(parent, entry.getName());
+        index = findChildNode(parent, entry.getName().toString());
 //      System.out.println("Differential mode -> ending to search");
       }
       else {
@@ -1444,7 +1444,7 @@
       if (index < 0) {
         // -(index + 1) is the location where to insert the new node
         index = -(index + 1);
-        child = new BasicNode(entry.getName());
+        child = new BasicNode(entry.getName().toString());
         parent.insert(child, index);
         updateNodeRendering(child, entry);
         insertIndex.add(index);
@@ -1530,15 +1530,14 @@
    * @param node the node to be rendered.
    * @param entry the search result for the entry that the node represents.
    */
-  private boolean updateNodeRendering(BasicNode node, SearchResult entry)
+  private boolean updateNodeRendering(BasicNode node, SearchResultEntry entry)
   throws NamingException {
     if (entry != null) {
       node.setNumSubOrdinates(getNumSubOrdinates(entry));
       node.setHasSubOrdinates(
           node.getNumSubOrdinates() > 0 || getHasSubOrdinates(entry));
       node.setReferral(getReferral(entry));
-      Set<String> ocValues = ConnectionUtils.getValues(entry,
-          OBJECTCLASS_ATTRIBUTE_TYPE_NAME);
+      Set<String> ocValues = asSetOfString(entry, OBJECTCLASS_ATTRIBUTE_TYPE_NAME);
       if (ocValues != null) {
         node.setObjectClassValues(ocValues.toArray(new String[ocValues.size()]));
       }
@@ -1565,7 +1564,7 @@
     } else {
       boolean useRdn = true;
       if (!RDN_ATTRIBUTE.equals(displayAttribute) && entry != null) {
-        String value = ConnectionUtils.getFirstValue(entry,displayAttribute);
+        String value = firstValueAsString(entry, displayAttribute);
         if (value != null) {
           if (showAttributeName) {
             value = displayAttribute+"="+value;
@@ -1620,20 +1619,16 @@
     return changed;
   }
 
-  private int getAciCount(SearchResult entry) throws NamingException
+  private int getAciCount(SearchResultEntry entry) throws NamingException
   {
     if ((displayFlags & DISPLAY_ACI_COUNT) != 0 && entry != null) {
-      Set<String> aciValues = ConnectionUtils.getValues(entry, "aci");
-      if (aciValues != null) {
-        return aciValues.size();
-      }
+      return asSetOfString(entry, "aci").size();
     }
     return 0;
   }
 
 
-  private Icon getNewIcon(BasicNode node, SearchResult entry)
-      throws NamingException
+  private Icon getNewIcon(BasicNode node, SearchResultEntry entry)
   {
     // Select the icon according the objectClass,...
     int modifiers = 0;
@@ -1654,11 +1649,7 @@
 
     SortedSet<String> objectClasses = new TreeSet<>();
     if (entry != null) {
-      Set<String> ocs = ConnectionUtils.getValues(entry, "objectClass");
-      if (ocs != null)
-      {
-        objectClasses.addAll(ocs);
-      }
+      objectClasses.addAll(asSetOfString(entry, "objectClass"));
     }
 
     if (node instanceof SuffixNode)
@@ -1832,9 +1823,9 @@
    * @return the value of the numSubordinates attribute.  0 if the attribute
    * could not be found.
    */
-  private static int getNumSubOrdinates(SearchResult entry) throws NamingException
+  private static int getNumSubOrdinates(SearchResultEntry entry) throws NamingException
   {
-    return toInt(ConnectionUtils.getFirstValue(entry, NUMSUBORDINATES_ATTR));
+    return toInt(firstValueAsString(entry, NUMSUBORDINATES_ATTR));
   }
 
   /**
@@ -1846,10 +1837,10 @@
    * of hasSubordinates and numSubordinates, returns {@code false} if none of
    * the attributes could be found.
    */
-  public static boolean getHasSubOrdinates(SearchResult entry)
+  public static boolean getHasSubOrdinates(SearchResultEntry entry)
   throws NamingException
   {
-    String v = ConnectionUtils.getFirstValue(entry, HASSUBORDINATES_ATTR);
+    String v = firstValueAsString(entry, HASSUBORDINATES_ATTR);
     if (v != null) {
       return "true".equalsIgnoreCase(v);
     }
@@ -1923,11 +1914,10 @@
    * @return the value of the ref attribute.  <CODE>null</CODE> if the attribute
    * could not be found.
    */
-  public static String[] getReferral(SearchResult entry) throws NamingException
+  public static String[] getReferral(SearchResultEntry entry) throws NamingException
   {
     String[] result = null;
-    Set<String> values = ConnectionUtils.getValues(entry,
-        OBJECTCLASS_ATTRIBUTE_TYPE_NAME);
+    Set<String> values = asSetOfString(entry, OBJECTCLASS_ATTRIBUTE_TYPE_NAME);
     if (values != null)
     {
       for (String value : values)
@@ -1935,8 +1925,7 @@
         boolean isReferral = "referral".equalsIgnoreCase(value);
         if (isReferral)
         {
-          Set<String> refValues = ConnectionUtils.getValues(entry,
-              ATTR_REFERRAL_URL);
+          Set<String> refValues = asSetOfString(entry, ATTR_REFERRAL_URL);
           if (refValues != null)
           {
             result = new String[refValues.size()];
diff --git a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/NodeRefresher.java b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/NodeRefresher.java
index 9319741..10acecd 100644
--- a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/NodeRefresher.java
+++ b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/NodeRefresher.java
@@ -16,8 +16,15 @@
  */
 package org.opends.guitools.controlpanel.browser;
 
+import static org.forgerock.opendj.ldap.LdapException.*;
+import static org.forgerock.opendj.ldap.ResultCode.*;
+import static org.forgerock.opendj.ldap.SearchScope.*;
+import static org.forgerock.opendj.ldap.requests.Requests.*;
+import static org.opends.admin.ads.util.ConnectionUtils.*;
 import static org.opends.messages.AdminToolMessages.*;
+import static org.opends.server.schema.SchemaConstants.*;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
@@ -35,13 +42,16 @@
 
 import org.forgerock.i18n.LocalizedIllegalArgumentException;
 import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.LdapException;
 import org.forgerock.opendj.ldap.RDN;
+import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
-import org.opends.admin.ads.util.ConnectionUtils;
+import org.forgerock.opendj.ldap.requests.SearchRequest;
+import org.forgerock.opendj.ldap.responses.SearchResultEntry;
+import org.forgerock.opendj.ldif.ConnectionEntryReader;
 import org.opends.admin.ads.util.ConnectionWrapper;
 import org.opends.guitools.controlpanel.ui.nodes.BasicNode;
 import org.opends.messages.AdminToolMessages;
-import org.opends.server.schema.SchemaConstants;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.HostPort;
 import org.opends.server.types.LDAPURL;
@@ -80,11 +90,11 @@
   private State state;
   private final boolean recursive;
 
-  private SearchResult localEntry;
-  private SearchResult remoteEntry;
+  private SearchResultEntry localEntry;
+  private SearchResultEntry remoteEntry;
   private LDAPURL remoteUrl;
   private boolean isLeafNode;
-  private final List<SearchResult> childEntries = new ArrayList<>();
+  private final List<SearchResultEntry> childEntries = new ArrayList<>();
   private final boolean differential;
   private Exception exception;
   private Object exceptionArg;
@@ -96,7 +106,7 @@
    * @param localEntry the local entry corresponding to the node.
    * @param recursive whether this task is recursive or not (children must be searched).
    */
-  NodeRefresher(BasicNode node, BrowserController ctlr, SearchResult localEntry, boolean recursive) {
+  NodeRefresher(BasicNode node, BrowserController ctlr, SearchResultEntry localEntry, boolean recursive) {
     super(node);
     controller = ctlr;
     state = State.QUEUED;
@@ -110,7 +120,7 @@
    * Returns the local entry the refresher is handling.
    * @return the local entry the refresher is handling.
    */
-  public SearchResult getLocalEntry() {
+  public SearchResultEntry getLocalEntry() {
     return localEntry;
   }
 
@@ -119,7 +129,7 @@
    * the entry is not a referral.
    * @return the remote entry for the node.
    */
-  public SearchResult getRemoteEntry() {
+  public SearchResultEntry getRemoteEntry() {
     return remoteEntry;
   }
 
@@ -145,7 +155,7 @@
    * Returns the child entries of the node.
    * @return the child entries of the node.
    */
-  public List<SearchResult> getChildEntries() {
+  public List<SearchResultEntry> getChildEntries() {
     return childEntries;
   }
 
@@ -184,16 +194,14 @@
    * @return the remote entry if the entry is a referral and the
    * BrowserController is following referrals and the local entry otherwise.
    */
-  public SearchResult getDisplayedEntry() {
-    SearchResult result;
+  public SearchResultEntry getDisplayedEntry() {
     if (controller.getFollowReferrals() && remoteEntry != null)
     {
-      result = remoteEntry;
+      return remoteEntry;
     }
     else {
-      result = localEntry;
+      return localEntry;
     }
-    return result;
   }
 
   /**
@@ -291,13 +299,11 @@
    */
   private boolean useCustomFilter()
   {
-    boolean result=false;
     if (controller.getFilter()!=null)
     {
-      result =
- !BrowserController.ALL_OBJECTS_FILTER.equals(controller.getFilter());
+      return !BrowserController.ALL_OBJECTS_FILTER.equals(controller.getFilter());
     }
-    return result;
+    return false;
   }
 
   /**
@@ -307,43 +313,39 @@
    *          the parent node we perform the search from.
    * @param conn
    *          the connection to be used.
-   * @throws NamingException
+   * @throws IOException
    *           if a problem occurred.
    */
-  private void searchForCustomFilter(BasicNode node, ConnectionWrapper conn)
-  throws NamingException
+  private void searchForCustomFilter(BasicNode node, ConnectionWrapper conn) throws IOException
   {
-    SearchControls ctls = controller.getBasicSearchControls();
-    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
-    ctls.setReturningAttributes(new String[] { SchemaConstants.NO_ATTRIBUTES });
-    ctls.setCountLimit(1);
-    NamingEnumeration<SearchResult> s =
-        conn.getLdapContext().search(new LdapName(node.getDN()),
-              controller.getFilter(),
-              ctls);
-    try
+    SearchRequest request = newSearchRequest(node.getDN(), WHOLE_SUBTREE, controller.getFilter(), NO_ATTRIBUTES)
+        .setSizeLimit(1);
+    try (ConnectionEntryReader s = conn.getConnection().search(request))
     {
-      if (!s.hasMore())
+      if (!s.hasNext())
       {
-        throw new NameNotFoundException("Entry "+node.getDN()+
+        throw newLdapException(NO_SUCH_OBJECT, "Entry " + node.getDN() +
             " does not verify filter "+controller.getFilter());
       }
-      while (s.hasMore())
+      while (s.hasNext())
       {
-        s.next();
+        s.readEntry();
       }
     }
-    catch (SizeLimitExceededException slme)
+    catch (LdapException e)
     {
-      // We are just searching for an entry, but if there is more than one
-      // this exception will be thrown.  We call sr.hasMore after the
-      // first entry has been retrieved to avoid sending a systematic
-      // abandon when closing the s NamingEnumeration.
-      // See CR 6976906.
-    }
-    finally
-    {
-      s.close();
+      if (e.getResult().getResultCode() == ResultCode.SIZE_LIMIT_EXCEEDED)
+      {
+        // We are just searching for an entry, but if there is more than one
+        // this exception will be thrown. We call sr.hasMore after the
+        // first entry has been retrieved to avoid sending a systematic
+        // abandon when closing the s NamingEnumeration.
+        // See CR 6976906.
+      }
+      else
+      {
+        throw e;
+      }
     }
   }
 
@@ -403,37 +405,29 @@
           searchForCustomFilter(node, conn);
         }
 
-        SearchControls ctls = controller.getBasicSearchControls();
-        ctls.setReturningAttributes(controller.getAttrsForRedSearch());
-        ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
-
-        NamingEnumeration<SearchResult> s =
-            conn.getLdapContext().search(new LdapName(node.getDN()),
-                controller.getObjectSearchFilter(),
-                ctls);
-        try
+        String filter = controller.getObjectSearchFilter();
+        SearchRequest request =
+            newSearchRequest(node.getDN(), BASE_OBJECT, filter, controller.getAttrsForRedSearch())
+            .setSizeLimit(controller.getMaxChildren());
+        try (ConnectionEntryReader s = conn.getConnection().search(request))
         {
-          while (s.hasMore())
+          while (s.hasNext())
           {
-            localEntry = s.next();
+            localEntry = s.readEntry();
             localEntry.setName(node.getDN());
           }
         }
-        finally
-        {
-          s.close();
-        }
         if (localEntry == null) {
           /* Not enough rights to read the entry or the entry simply does not exist */
-          throw new NameNotFoundException("Can't find entry: "+node.getDN());
+          throw newLdapException(ResultCode.NO_SUCH_OBJECT, "Can't find entry: " + node.getDN());
         }
         throwAbandonIfNeeded(null);
       } else {
           changeStateTo(State.FINISHED);
       }
     }
-    catch(NamingException x) {
-        throwAbandonIfNeeded(x);
+    catch(IOException | NamingException x) {
+      throwAbandonIfNeeded(x);
     }
     finally {
       if (conn != null) {
@@ -478,7 +472,7 @@
   throws SearchAbandonException {
     LDAPConnectionPool connectionPool = controller.getConnectionPool();
     LDAPURL url = null;
-    SearchResult entry = null;
+    SearchResultEntry entry = null;
     String remoteDn = null;
     Exception lastException = null;
     Object lastExceptionArg = null;
@@ -506,9 +500,9 @@
              have to use the DN of the entry that contains the
              referral... */
           if (remoteEntry != null) {
-            remoteDn = remoteEntry.getName();
+            remoteDn = remoteEntry.getName().toString();
           } else {
-            remoteDn = localEntry.getName();
+            remoteDn = localEntry.getName().toString();
           }
           /* We have to recreate the url including the target DN we are using */
           url = new LDAPURL(url.getScheme(), url.getHost(), url.getPort(),
@@ -521,30 +515,24 @@
           searchForCustomFilter(remoteDn, conn);
         }
 
-        int scope = getJNDIScope(url);
         String filter = getJNDIFilter(url);
 
-        SearchControls ctls = controller.getBasicSearchControls();
-        ctls.setReturningAttributes(controller.getAttrsForBlackSearch());
-        ctls.setSearchScope(scope);
-        ctls.setCountLimit(1);
-        NamingEnumeration<SearchResult> sr = conn.getLdapContext().search(remoteDn,
-            filter,
-            ctls);
-        try
+        SearchRequest request = newSearchRequest(remoteDn, url.getScope(), filter, controller.getAttrsForBlackSearch())
+            .setSizeLimit(controller.getMaxChildren());
+        try (ConnectionEntryReader sr = conn.getConnection().search(request))
         {
           boolean found = false;
-          while (sr.hasMore())
+          while (sr.hasNext())
           {
-            entry = sr.next();
+            entry = sr.readEntry();
             String name;
-            if (entry.getName().length() == 0)
+            if (entry.getName().isRootDN())
             {
               name = remoteDn;
             }
             else
             {
-              name = unquoteRelativeName(entry.getName())+","+remoteDn;
+              name = unquoteRelativeName(entry.getName().toString()) + "," + remoteDn;
             }
             entry.setName(name);
             found = true;
@@ -554,24 +542,28 @@
             throw new NameNotFoundException();
           }
         }
-        catch (SizeLimitExceededException sle)
+        catch (LdapException e)
         {
-          // We are just searching for an entry, but if there is more than one
-          // this exception will be thrown.  We call sr.hasMore after the
-          // first entry has been retrieved to avoid sending a systematic
-          // abandon when closing the sr NamingEnumeration.
-          // See CR 6976906.
-        }
-        finally
-        {
-          sr.close();
+          if (e.getResult().getResultCode() == ResultCode.SIZE_LIMIT_EXCEEDED)
+          {
+            // We are just searching for an entry, but if there is more than one
+            // this exception will be thrown. We call sr.hasMore after the
+            // first entry has been retrieved to avoid sending a systematic
+            // abandon when closing the sr NamingEnumeration.
+            // See CR 6976906.
+          }
+          else
+          {
+            throw e;
+          }
         }
         throwAbandonIfNeeded(null);
       }
       catch (InterruptedNamingException x) {
         throwAbandonIfNeeded(x);
       }
-      catch (NamingException | LocalizedIllegalArgumentException | DirectoryException x) {
+      catch (NamingException | IOException | LocalizedIllegalArgumentException | DirectoryException x)
+      {
         lastException = x;
         lastExceptionArg = referral[i];
       }
@@ -636,7 +628,7 @@
       runDetectChildrenManually();
     }
     else {
-      SearchResult entry = getDisplayedEntry();
+      SearchResultEntry entry = getDisplayedEntry();
       isLeafNode = !BrowserController.getHasSubOrdinates(entry);
     }
   }
@@ -649,63 +641,48 @@
   private void runDetectChildrenManually() throws SearchAbandonException {
     BasicNode parentNode = getNode();
     ConnectionWrapper conn = null;
-    NamingEnumeration<SearchResult> searchResults = null;
 
     try {
       // We set the search constraints so that only one entry is returned.
       // It's enough to know if the entry has children or not.
-      SearchControls ctls = controller.getBasicSearchControls();
-      ctls.setCountLimit(1);
-      ctls.setReturningAttributes(
-          new String[] { SchemaConstants.NO_ATTRIBUTES });
-      if (useCustomFilter())
+      // Send an LDAP search
+      conn = controller.findConnectionForDisplayedEntry(parentNode);
+      SearchRequest request = newSearchRequest(
+              controller.findBaseDNForChildEntries(parentNode),
+              useCustomFilter() ? WHOLE_SUBTREE : BASE_OBJECT,
+              controller.getChildSearchFilter(),
+              NO_ATTRIBUTES)
+          .setSizeLimit(1);
+      try (ConnectionEntryReader searchResults = conn.getConnection().search(request))
       {
-        ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+        throwAbandonIfNeeded(null);
+        // Check if parentNode has children
+        isLeafNode = !searchResults.hasNext();
+      }
+    }
+    catch (LdapException e)
+    {
+      if (e.getResult().getResultCode().equals(ResultCode.SIZE_LIMIT_EXCEEDED))
+      {
+        // We are just searching for an entry, but if there is more than one
+        // this exception will be thrown. We call sr.hasMore after the
+        // first entry has been retrieved to avoid sending a systematic
+        // abandon when closing the searchResults NamingEnumeration.
+        // See CR 6976906.
       }
       else
       {
-        ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
-      }
-      // Send an LDAP search
-      conn = controller.findConnectionForDisplayedEntry(parentNode);
-      searchResults = conn.getLdapContext().search(
-          new LdapName(controller.findBaseDNForChildEntries(parentNode)),
-          controller.getChildSearchFilter(),
-          ctls);
-
-      throwAbandonIfNeeded(null);
-      isLeafNode = true;
-      // Check if parentNode has children
-      while (searchResults.hasMoreElements()) {
-        isLeafNode = false;
+        throwAbandonIfNeeded(e);
       }
     }
-    catch (SizeLimitExceededException e)
+    catch (NamingException x)
     {
-      // We are just searching for an entry, but if there is more than one
-      // this exception will be thrown.  We call sr.hasMore after the
-      // first entry has been retrieved to avoid sending a systematic
-      // abandon when closing the searchResults NamingEnumeration.
-      // See CR 6976906.
-    }
-    catch (NamingException x) {
       throwAbandonIfNeeded(x);
     }
     finally {
       if (conn != null) {
         controller.releaseLDAPConnection(conn);
       }
-      if (searchResults != null)
-      {
-        try
-        {
-          searchResults.close();
-        }
-        catch (NamingException x)
-        {
-          throwAbandonIfNeeded(x);
-        }
-      }
     }
   }
 
@@ -716,7 +693,7 @@
    * Note: *usable* means *usable for detecting children presence*.
    */
   private boolean isNumSubOrdinatesUsable() throws NamingException {
-    SearchResult entry = getDisplayedEntry();
+    SearchResultEntry entry = getDisplayedEntry();
     boolean hasSubOrdinates = BrowserController.getHasSubOrdinates(entry);
     if (!hasSubOrdinates)
     {
@@ -738,16 +715,6 @@
 
     try {
       // Send an LDAP search
-      SearchControls ctls = controller.getBasicSearchControls();
-      if (useCustomFilter())
-      {
-        ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
-      }
-      else
-      {
-        ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
-      }
-      ctls.setReturningAttributes(controller.getAttrsForRedSearch());
       conn = controller.findConnectionForDisplayedEntry(parentNode);
       String parentDn = controller.findBaseDNForChildEntries(parentNode);
       int parentComponents;
@@ -761,22 +728,23 @@
         throw new RuntimeException("Error decoding dn: "+parentDn+" . "+t,
             t);
       }
-      NamingEnumeration<SearchResult> entries = conn.getLdapContext().search(
-            new LdapName(parentDn),
-                controller.getChildSearchFilter(),
-                ctls);
 
-      try
+      SearchScope scope = useCustomFilter() ? WHOLE_SUBTREE : SINGLE_LEVEL;
+      SearchRequest request =
+          newSearchRequest(parentDn, scope, controller.getChildSearchFilter(), controller.getAttrsForRedSearch())
+              .setSizeLimit(controller.getMaxChildren());
+
+      try (ConnectionEntryReader entries = conn.getConnection().search(request))
       {
-        while (entries.hasMore())
+        while (entries.hasNext())
         {
-          SearchResult r = entries.next();
-          if (r.getName().length() == 0)
+          SearchResultEntry r = entries.readEntry();
+          if (r.getName().isRootDN())
           {
             continue;
           }
 
-          String name = unquoteRelativeName(r.getName()) + "," + parentDn;
+          String name = unquoteRelativeName(r.getName().toString()) + "," + parentDn;
           boolean add = false;
           if (useCustomFilter())
           {
@@ -800,48 +768,10 @@
               // search for the parent and add it.
               RDN[] rdns = new RDN[parentComponents + 1];
               final DN parentToAddDN = dn.parent(dn.size() - rdns.length);
-              boolean mustAddParent = mustAddParent(parentToAddDN);
+              boolean mustAddParent = mustAddParent(parentToAddDN) && mustAddParent2(parentToAddDN);
               if (mustAddParent)
               {
-                final boolean resultValue[] = {true};
-                // Check the children added to the tree
-                try
-                {
-                  SwingUtilities.invokeAndWait(new Runnable()
-                  {
-                    @Override
-                    public void run()
-                    {
-                      for (int i=0; i<getNode().getChildCount(); i++)
-                      {
-                        BasicNode node = (BasicNode)getNode().getChildAt(i);
-                        try
-                        {
-                          DN dn = DN.valueOf(node.getDN());
-                          if (dn.equals(parentToAddDN))
-                          {
-                            resultValue[0] = false;
-                            break;
-                          }
-                        }
-                        catch (Throwable t)
-                        {
-                          throw new RuntimeException("Error decoding dn: "+
-                              node.getDN()+" . "+t, t);
-                        }
-                      }
-                    }
-                  });
-                }
-                catch (Throwable t)
-                {
-                  // Ignore
-                }
-                mustAddParent = resultValue[0];
-              }
-              if (mustAddParent)
-              {
-                SearchResult parentResult = searchManuallyEntry(conn, parentToAddDN.toString());
+                SearchResultEntry parentResult = searchManuallyEntry(conn, parentToAddDN.toString());
                 childEntries.add(parentResult);
               }
             }
@@ -863,17 +793,21 @@
           throwAbandonIfNeeded(null);
         }
       }
-      finally
+    }
+    catch (LdapException e)
+    {
+      if (e.getResult().getResultCode() == ResultCode.SIZE_LIMIT_EXCEEDED)
       {
-        entries.close();
+        parentNode.setSizeLimitReached(true);
+      }
+      else
+      {
+        throwAbandonIfNeeded(e);
       }
     }
-    catch (SizeLimitExceededException slee)
+    catch (NamingException | IOException e)
     {
-      parentNode.setSizeLimitReached(true);
-    }
-    catch (NamingException x) {
-      throwAbandonIfNeeded(x);
+      throwAbandonIfNeeded(e);
     }
     finally {
       if (conn != null)
@@ -883,14 +817,52 @@
     }
   }
 
+  private boolean mustAddParent2(final DN parentToAddDN)
+  {
+    final boolean resultValue[] = {true};
+    // Check the children added to the tree
+    try
+    {
+      SwingUtilities.invokeAndWait(new Runnable()
+      {
+        @Override
+        public void run()
+        {
+          for (int i=0; i<getNode().getChildCount(); i++)
+          {
+            BasicNode node = (BasicNode)getNode().getChildAt(i);
+            try
+            {
+              DN dn = DN.valueOf(node.getDN());
+              if (dn.equals(parentToAddDN))
+              {
+                resultValue[0] = false;
+                break;
+              }
+            }
+            catch (Throwable t)
+            {
+              throw new RuntimeException("Error decoding dn: "+
+                  node.getDN()+" . "+t, t);
+            }
+          }
+        }
+      });
+    }
+    catch (Throwable t)
+    {
+      // Ignore
+    }
+    return resultValue[0];
+  }
+
   private boolean mustAddParent(final DN parentToAddDN)
   {
-    for (SearchResult addedEntry : childEntries)
+    for (SearchResultEntry addedEntry : childEntries)
     {
       try
       {
-        DN addedDN = DN.valueOf(addedEntry.getName());
-        if (addedDN.equals(parentToAddDN))
+        if (addedEntry.getName().equals(parentToAddDN))
         {
           return false;
         }
@@ -910,32 +882,22 @@
    * @param dn the DN of the entry to be searched.
    * @throws NamingException if an error occurs.
    */
-  private SearchResult searchManuallyEntry(ConnectionWrapper conn, String dn)
-  throws NamingException
+  private SearchResultEntry searchManuallyEntry(ConnectionWrapper conn, String dn) throws IOException
   {
-    // Send an LDAP search
-    SearchControls ctls = controller.getBasicSearchControls();
-    ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
-    ctls.setReturningAttributes(controller.getAttrsForRedSearch());
-    NamingEnumeration<SearchResult> entries = conn.getLdapContext().search(
-          new LdapName(dn),
-              controller.getObjectSearchFilter(),
-              ctls);
+    SearchRequest request =
+        newSearchRequest(dn, BASE_OBJECT, controller.getObjectSearchFilter(), controller.getAttrsForRedSearch())
+        .setSizeLimit(controller.getMaxChildren());
 
-    SearchResult sr = null;
-    try
+    try (ConnectionEntryReader entries = conn.getConnection().search(request))
     {
-      while (entries.hasMore())
+      SearchResultEntry sr = null;
+      while (entries.hasNext())
       {
-        sr = entries.next();
+        sr = entries.readEntry();
         sr.setName(dn);
       }
+      return sr;
     }
-    finally
-    {
-      entries.close();
-    }
-    return sr;
   }
 
   /** Utilities. */
@@ -1032,15 +994,15 @@
    * and the attribute 'ref' is present and <CODE>false</CODE> otherwise.
    * @throws NamingException if an error occurs.
    */
-  private static boolean isReferralEntry(SearchResult entry) throws NamingException
+  private static boolean isReferralEntry(SearchResultEntry entry) throws NamingException
   {
-    Set<String> ocValues = ConnectionUtils.getValues(entry, "objectClass");
+    Set<String> ocValues = asSetOfString(entry, "objectClass");
     if (ocValues != null) {
       for (String value : ocValues)
       {
         boolean isReferral = "referral".equalsIgnoreCase(value);
         if (isReferral) {
-          return ConnectionUtils.getFirstValue(entry, "ref") != null;
+          return firstValueAsString(entry, "ref") != null;
         }
       }
     }

--
Gitblit v1.10.0