mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Jean-Noël Rouvignac
11.02.2016 45a05a46b927f19865e6a748873d70efe9a99ac5
Partial OPENDJ-2625 Convert all code that uses JNDI to use the SDK instead

When user required entries to be sorted or to follow referrals,
the control-panel relied on the InitialLdapContext carrying the controls
(like server side sort or manageDsaIT).
To mimick this behaviour, I added the ConnectionWithControls class.
This class is now used everywhere.

Also switched some code to use DN.
1 files added
16 files modified
935 ■■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/BrowserController.java 260 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/ConnectionWithControls.java 211 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/LDAPConnectionPool.java 72 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/NodeRefresher.java 129 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/AddToGroupTask.java 3 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/DeleteEntryTask.java 18 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/ModifyEntryTask.java 12 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/NewEntryTask.java 45 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/ResetUserPasswordTask.java 11 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/AbstractBrowseEntriesPanel.java 69 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/AbstractNewEntryPanel.java 3 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/AddToGroupPanel.java 25 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/BrowseEntriesPanel.java 36 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/DuplicateEntryPanel.java 6 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/NewGroupPanel.java 9 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java 18 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/util/LDAPEntryReader.java 8 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/BrowserController.java
@@ -20,11 +20,12 @@
import static org.opends.server.util.ServerConstants.*;
import java.awt.Font;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
@@ -34,10 +35,6 @@
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.naming.directory.SearchControls;
import javax.naming.ldap.Control;
import javax.naming.ldap.ManageReferralControl;
import javax.naming.ldap.SortControl;
import javax.naming.ldap.SortKey;
import javax.swing.Icon;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
@@ -49,6 +46,11 @@
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.Entry;
import org.forgerock.opendj.ldap.Filter;
import org.forgerock.opendj.ldap.SortKey;
import org.forgerock.opendj.ldap.controls.Control;
import org.forgerock.opendj.ldap.controls.ManageDsaITRequestControl;
import org.forgerock.opendj.ldap.controls.ServerSideSortRequestControl;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.opends.admin.ads.ADSContext;
import org.opends.admin.ads.util.ConnectionWrapper;
@@ -77,12 +79,20 @@
public class BrowserController
implements TreeExpansionListener, ReferralAuthenticationListener
{
  private static final Logger LOG = Logger.getLogger(BrowserController.class.getName());
  /** The mask used to display the number of ACIs or not. */
  private static final int DISPLAY_ACI_COUNT = 0x01;
  /** The list of attributes that are used to sort the entries (if the sorting option is used). */
  private static final String[] SORT_ATTRIBUTES =
      { "cn", "givenname", "o", "ou", "sn", "uid" };
  private static final SortKey[] SORT_ATTRIBUTES = {
    new SortKey("cn"),
    new SortKey("givenname"),
    new SortKey("o"),
    new SortKey("ou"),
    new SortKey("sn"),
    new SortKey("uid")
  };
  /**
   * This is a key value.  It is used to specify that the attribute that should
@@ -91,8 +101,8 @@
  private static final String RDN_ATTRIBUTE = "rdn attribute";
  /** The filter used to retrieve all the entries. */
  public static final String ALL_OBJECTS_FILTER =
    "(|(objectClass=*)(objectClass=ldapsubentry))";
  public static final Filter ALL_OBJECTS_FILTER = Filter.valueOf(
      "(|(objectClass=*)(objectClass=ldapsubentry))");
  private static final String NUMSUBORDINATES_ATTR = "numsubordinates";
  private static final String HASSUBORDINATES_ATTR = "hassubordinates";
@@ -101,17 +111,15 @@
  private final JTree tree;
  private final DefaultTreeModel treeModel;
  private final RootNode rootNode;
  private int displayFlags;
  private String displayAttribute;
  private final boolean showAttributeName;
  private ConnectionWrapper connConfig;
  private ConnectionWrapper connUserData;
  private boolean followReferrals;
  private boolean sorted;
  private boolean showContainerOnly;
  private int displayFlags = DISPLAY_ACI_COUNT;
  private String displayAttribute = RDN_ATTRIBUTE;
  private final boolean showAttributeName = false;
  private ConnectionWithControls connConfig;
  private ConnectionWithControls connUserData;
  private boolean showContainerOnly = true;
  private boolean automaticExpand;
  private boolean automaticallyExpandedNode;
  private String[] containerClasses;
  private String[] containerClasses = new String[0];
  private NumSubordinateHacker numSubordinateHacker;
  private int queueTotalSize;
  private int maxChildren;
@@ -121,10 +129,9 @@
  private final NodeSearcherQueue refreshQueue;
  private String filter;
  private static final Logger LOG =
    Logger.getLogger(BrowserController.class.getName());
  private ServerSideSortRequestControl sortControl;
  private ManageDsaITRequestControl followReferralsControl;
  private Filter filter;
  /**
   * Constructor of the BrowserController.
@@ -134,8 +141,7 @@
   * @param ipool the icon pool to be used to retrieve the icons that will be
   * used to render the nodes in the tree.
   */
  public BrowserController(JTree tree, LDAPConnectionPool cpool,
      IconPool ipool)
  public BrowserController(JTree tree, LDAPConnectionPool cpool, IconPool ipool)
  {
    this.tree = tree;
    iconPool = ipool;
@@ -145,14 +151,6 @@
    tree.setModel(treeModel);
    tree.addTreeExpansionListener(this);
    tree.setCellRenderer(new BrowserCellRenderer());
    displayFlags = DISPLAY_ACI_COUNT;
    showAttributeName = false;
    displayAttribute = RDN_ATTRIBUTE;
    followReferrals = false;
    sorted = false;
    showContainerOnly = true;
    containerClasses = new String[0];
    queueTotalSize = 0;
    connectionPool = cpool;
    connectionPool.addReferralAuthenticationListener(this);
@@ -175,21 +173,18 @@
   * the configuration base DNs.
   * @param connUserData the connection to be used to retrieve the data in the
   * user base DNs.
   * @throws NamingException if an error occurs.
   */
  public void setConnections(
      ServerDescriptor server,
      ConnectionWrapper connConfiguration,
      ConnectionWrapper connUserData) throws NamingException {
      ConnectionWrapper connUserData) {
    String rootNodeName;
    if (connConfiguration != null)
    {
      this.connConfig = connConfiguration;
      this.connUserData = connUserData;
      connConfig.getLdapContext().setRequestControls(getConfigurationRequestControls());
      connUserData.getLdapContext().setRequestControls(getRequestControls());
      rootNodeName = new HostPort(server.getHostname(), connConfig.getHostPort().getPort()).toString();
      this.connConfig = new ConnectionWithControls(connConfiguration, sortControl, followReferralsControl);
      this.connUserData = new ConnectionWithControls(connUserData, sortControl, followReferralsControl);
      rootNodeName = HostPort.toString(server.getHostname(),
                                       connConfig.getConnectionWrapper().getHostPort().getPort());
    }
    else {
      rootNodeName = "";
@@ -202,7 +197,7 @@
   * Return the connection for accessing the directory configuration.
   * @return the connection for accessing the directory configuration.
   */
  public ConnectionWrapper getConfigurationConnection() {
  public ConnectionWithControls getConfigurationConnection() {
    return connConfig;
  }
@@ -210,7 +205,7 @@
   * Return the connection for accessing the directory user data.
   * @return the connection for accessing the directory user data.
   */
  public ConnectionWrapper getUserDataConnection() {
  public ConnectionWithControls getUserDataConnection() {
    return connUserData;
  }
@@ -342,6 +337,11 @@
   */
  public void setDisplayAttribute(String displayAttribute) {
    this.displayAttribute = displayAttribute;
    restartRefresh();
  }
  private void restartRefresh()
  {
    stopRefresh();
    removeAllChildNodes(rootNode, true /* Keep suffixes */);
    startRefresh(null);
@@ -384,55 +384,49 @@
  /**
   * Return true if this controller follows referrals.
   * @return {@code true} if this controller follows referrals and
   * {@code false} otherwise.
   *
   * @return {@code true} if this controller follows referrals, {@code false} otherwise.
   */
  public boolean getFollowReferrals() {
    return followReferrals;
  public boolean isFollowReferrals() {
    return followReferralsControl != null;
  }
  /**
   * Enable/display the following of referrals.
   * This routine starts a refresh on each referral node.
   * @param followReferrals whether to follow referrals or not.
   * @throws NamingException if there is an error updating the request controls
   * of the internal connections.
   */
  public void setFollowReferrals(boolean followReferrals) throws NamingException
  {
    this.followReferrals = followReferrals;
    stopRefresh();
    removeAllChildNodes(rootNode, true /* Keep suffixes */);
    connConfig.getLdapContext().setRequestControls(getConfigurationRequestControls());
    connUserData.getLdapContext().setRequestControls(getRequestControls());
    connectionPool.setRequestControls(getRequestControls());
    startRefresh(null);
  public void setFollowReferrals(boolean followReferrals) {
    followReferralsControl = followReferrals ? ManageDsaITRequestControl.newControl(false) : null;
    resetRequestControls();
    restartRefresh();
  }
  /**
   * Return true if entries are displayed sorted.
   * @return {@code true} if entries are displayed sorted and
   * {@code false} otherwise.
   *
   * @return {@code true} if entries are displayed sorted, {@code false} otherwise.
   */
  public boolean isSorted() {
    return sorted;
    return sortControl != null;
  }
  /**
   * Enable/disable entry sort.
   * This routine collapses the JTree and invokes startRefresh().
   * @param sorted whether to sort the entries or not.
   * @throws NamingException if there is an error updating the request controls
   * of the internal connections.
   */
  public void setSorted(boolean sorted) throws NamingException {
    stopRefresh();
    removeAllChildNodes(rootNode, true /* Keep suffixes */);
    this.sorted = sorted;
    connConfig.getLdapContext().setRequestControls(getConfigurationRequestControls());
    connUserData.getLdapContext().setRequestControls(getRequestControls());
    connectionPool.setRequestControls(getRequestControls());
    startRefresh(null);
  public void setSorted(boolean sorted) {
    sortControl = sorted ? ServerSideSortRequestControl.newControl(false, SORT_ATTRIBUTES) : null;
    resetRequestControls();
    restartRefresh();
  }
  private void resetRequestControls()
  {
    this.connConfig.setRequestControls(sortControl, followReferralsControl);
    this.connUserData.setRequestControls(sortControl, followReferralsControl);
    this.connectionPool.setRequestControls(sortControl, followReferralsControl);
  }
  /**
@@ -531,7 +525,7 @@
    BasicNode parentNode = parentInfo.getNode();
    BasicNode childNode = new BasicNode(newEntryDn);
    int childIndex;
    if (sorted) {
    if (isSorted()) {
      childIndex = findChildNode(parentNode, newEntryDn);
      if (childIndex >= 0) {
        throw new IllegalArgumentException("Duplicate DN " + newEntryDn);
@@ -797,7 +791,7 @@
   * entries.
   * @param filter the LDAP filter.
   */
  public void setFilter(String filter)
  public void setFilter(Filter filter)
  {
    this.filter = filter;
  }
@@ -806,7 +800,7 @@
   * Returns the filter that is being used to search the entries.
   * @return the filter that is being used to search the entries.
   */
  public String getFilter()
  public Filter getFilter()
  {
    return filter;
  }
@@ -815,7 +809,7 @@
   * Returns the filter used to make a object base search.
   * @return the filter used to make a object base search.
   */
  String getObjectSearchFilter()
  Filter getObjectSearchFilter()
  {
    return ALL_OBJECTS_FILTER;
  }
@@ -826,10 +820,15 @@
   * container entries. If not, the filter will select all the children.
   * @return the LDAP search filter to use for searching child entries.
   */
  String getChildSearchFilter() {
    String result;
    if (showContainerOnly) {
      if (followReferrals) {
  Filter getChildSearchFilter()
  {
    if (!showContainerOnly)
    {
      return filter;
    }
    String result = "(|(&(hasSubordinates=true)" + filter + ")";
    if (isFollowReferrals()) {
        /* In the case we are following referrals, we have to consider referrals
         as nodes.
         Suppose the following scenario: a referral points to a remote entry
@@ -848,21 +847,15 @@
         This is minor compared to the impossibility of browsing a subtree with
         the NODE/LEAF layout.
         */
        result = "(|(&(hasSubordinates=true)"+filter+")(objectClass=referral)";
      } else {
        result = "(|(&(hasSubordinates=true)"+filter+")";
      result += "(objectClass=referral)";
      }
      for (String containerClass : containerClasses)
      {
        result += "(objectClass=" + containerClass + ")";
      }
      result += ")";
    }
    else {
      result = filter;
    }
    return result;
    return Filter.valueOf(result);
  }
  /**
@@ -871,8 +864,7 @@
   * @throws NamingException if there is an error retrieving the connection.
   * @return the LDAP connection to reading the base entry of a node.
   */
  ConnectionWrapper findConnectionForLocalEntry(BasicNode node)
  throws NamingException {
  ConnectionWithControls findConnectionForLocalEntry(BasicNode node) throws NamingException {
    return findConnectionForLocalEntry(node, isConfigurationNode(node));
  }
@@ -883,7 +875,7 @@
   * @throws NamingException if there is an error retrieving the connection.
   * @return the LDAP connection to reading the base entry of a node.
   */
  private ConnectionWrapper findConnectionForLocalEntry(BasicNode node,
  private ConnectionWithControls findConnectionForLocalEntry(BasicNode node,
      boolean isConfigurationNode) throws NamingException
  {
    if (node == rootNode) {
@@ -936,8 +928,7 @@
   * @return the LDAP connection to search the displayed entry.
   * @throws NamingException if there is an error retrieving the connection.
   */
  public ConnectionWrapper findConnectionForDisplayedEntry(BasicNode node)
  throws NamingException {
  public ConnectionWithControls findConnectionForDisplayedEntry(BasicNode node) throws NamingException {
    return findConnectionForDisplayedEntry(node, isConfigurationNode(node));
  }
@@ -949,9 +940,9 @@
   * @return the LDAP connection to search the displayed entry.
   * @throws NamingException if there is an error retrieving the connection.
   */
  private ConnectionWrapper findConnectionForDisplayedEntry(BasicNode node,
  private ConnectionWithControls findConnectionForDisplayedEntry(BasicNode node,
      boolean isConfigurationNode) throws NamingException {
    if (followReferrals && node.getRemoteUrl() != null)
    if (isFollowReferrals() && node.getRemoteUrl() != null)
    {
      return connectionPool.getConnection(node.getRemoteUrl());
    }
@@ -963,7 +954,7 @@
   * selectConnectionForBaseEntry().
   * @param conn the connection to be released.
   */
  void releaseLDAPConnection(ConnectionWrapper conn) {
  void releaseLDAPConnection(ConnectionWithControls conn) {
    if (conn != connConfig && conn != connUserData)
    {
      // Thus it comes from the connection pool
@@ -977,8 +968,9 @@
   * @return the local entry URL for a given node.
   */
  LDAPURL findUrlForLocalEntry(BasicNode node) {
    ConnectionWrapper conn = connConfig.getConnectionWrapper();
    if (node == rootNode) {
      return LDAPConnectionPool.makeLDAPUrl(connConfig.getHostPort(), "", connConfig.isLdaps());
      return LDAPConnectionPool.makeLDAPUrl(conn.getHostPort(), "", conn.isLdaps());
    }
    final BasicNode parent = (BasicNode) node.getParent();
    if (parent != null)
@@ -986,7 +978,7 @@
      final LDAPURL parentUrl = findUrlForDisplayedEntry(parent);
      return LDAPConnectionPool.makeLDAPUrl(parentUrl, node.getDN().toString());
    }
    return LDAPConnectionPool.makeLDAPUrl(connConfig.getHostPort(), node.getDN().toString(), connConfig.isLdaps());
    return LDAPConnectionPool.makeLDAPUrl(conn.getHostPort(), node.getDN().toString(), conn.isLdaps());
  }
  /**
@@ -996,7 +988,7 @@
   */
  private LDAPURL findUrlForDisplayedEntry(BasicNode node)
  {
    if (followReferrals && node.getRemoteUrl() != null) {
    if (isFollowReferrals() && node.getRemoteUrl() != null) {
      return node.getRemoteUrl();
    }
    return findUrlForLocalEntry(node);
@@ -1011,11 +1003,11 @@
   * @param node the node.
   * @return the DN to use for searching children of a given node.
   */
  String findBaseDNForChildEntries(BasicNode node) {
    if (followReferrals && node.getRemoteUrl() != null) {
      return node.getRemoteUrl().getRawBaseDN();
  DN findBaseDNForChildEntries(BasicNode node) {
    if (isFollowReferrals() && node.getRemoteUrl() != null) {
      return DN.valueOf(node.getRemoteUrl().getRawBaseDN());
    }
    return node.getDN().toString();
    return node.getDN();
  }
  /**
@@ -1025,7 +1017,7 @@
   * {@code false} otherwise.
   */
  private boolean isDisplayedEntryRemote(BasicNode node) {
    if (followReferrals) {
    if (isFollowReferrals()) {
      if (node == rootNode) {
        return false;
      }
@@ -1099,48 +1091,18 @@
   * Returns the request controls to search user data.
   * @return the request controls to search user data.
   */
  private Control[] getRequestControls()
  private List<Control> getRequestControls()
  {
    Control ctls[];
    if (followReferrals)
    List<Control> controls = new LinkedList<>();
    if (sortControl != null)
    {
      ctls = new Control[sorted ? 2 : 1];
      controls.add(sortControl);
    }
    else
    if (isFollowReferrals())
    {
      ctls = new Control[sorted ? 1 : 0];
      controls.add(followReferralsControl);
    }
    if (sorted)
    {
      SortKey[] keys = new SortKey[SORT_ATTRIBUTES.length];
      for (int i=0; i<keys.length; i++) {
        keys[i] = new SortKey(SORT_ATTRIBUTES[i]);
      }
      try
      {
        ctls[0] = new SortControl(keys, false);
      }
      catch (IOException ioe)
      {
        // Bug
        throw new RuntimeException("Unexpected encoding exception: "+ioe,
            ioe);
      }
    }
    if (followReferrals)
    {
      ctls[ctls.length - 1] = new ManageReferralControl(false);
    }
    return ctls;
  }
  /**
   * Returns the request controls to search configuration data.
   * @return the request controls to search configuration data.
   */
  private Control[] getConfigurationRequestControls()
  {
    return getRequestControls();
    return controls;
  }
  /**
@@ -1165,11 +1127,10 @@
   * @param task the task that progressed.
   * @param oldState the previous state of the task.
   * @param newState the new state of the task.
   * @throws NamingException if there is an error reading entries.
   */
  private void refreshTaskDidProgress(NodeRefresher task,
      NodeRefresher.State oldState,
      NodeRefresher.State newState) throws NamingException {
      NodeRefresher.State newState) {
    BasicNode node = task.getNode();
    boolean nodeChanged = false;
@@ -1344,9 +1305,8 @@
  /**
   * Updates the child nodes for a given task.
   * @param task the task.
   * @throws NamingException if an error occurs.
   */
  private void updateChildNodes(NodeRefresher task) throws NamingException {
  private void updateChildNodes(NodeRefresher task) {
    BasicNode parent = task.getNode();
    ArrayList<Integer> insertIndex = new ArrayList<>();
    ArrayList<Integer> changedIndex = new ArrayList<>();
@@ -1454,8 +1414,7 @@
   * @param entry the search result for the entry that the node represents.
   * @return whether the node display changed
   */
  private boolean updateNodeRendering(BasicNode node, SearchResultEntry entry)
  throws NamingException {
  private boolean updateNodeRendering(BasicNode node, SearchResultEntry entry) {
    if (entry != null) {
      node.setNumSubOrdinates(getNumSubOrdinates(entry));
      node.setHasSubOrdinates(
@@ -1545,7 +1504,7 @@
  private String getRDN(BasicNode node)
  {
    if (followReferrals && node.getRemoteUrl() != null) {
    if (isFollowReferrals() && node.getRemoteUrl() != null) {
      if (showAttributeName) {
        return node.getRemoteRDNWithAttributeName();
      } else {
@@ -1561,7 +1520,7 @@
    }
  }
  private int getAciCount(SearchResultEntry entry) throws NamingException
  private int getAciCount(SearchResultEntry entry)
  {
    if ((displayFlags & DISPLAY_ACI_COUNT) != 0 && entry != null) {
      return asSetOfString(entry, "aci").size();
@@ -1610,7 +1569,7 @@
   * @param childDn the DN of the entry that is being searched.
   * @return the index of the node matching childDn.
   */
  public int findChildNode(BasicNode parent, DN childDn) {
  public static int findChildNode(BasicNode parent, DN childDn) {
    int childCount = parent.getChildCount();
    int i = 0;
    while (i < childCount
@@ -1700,7 +1659,7 @@
   * @throws IllegalArgumentException if a node with the given dn exists but
   * is not a suffix node.
   */
  private SuffixNode findSuffixNode(DN suffixDn, SuffixNode suffixNode)
  private static SuffixNode findSuffixNode(DN suffixDn, SuffixNode suffixNode)
      throws IllegalArgumentException
  {
    if (suffixNode.getDN().equals(suffixDn)) {
@@ -1797,11 +1756,10 @@
   * Returns the value of the 'ref' attribute.
   * {@code null} if the attribute is not present.
   * @param entry the entry to analyze.
   * @throws NamingException if an error occurs.
   * @return the value of the ref attribute.  {@code null} if the attribute
   * could not be found.
   */
  public static String[] getReferral(SearchResultEntry entry) throws NamingException
  public static String[] getReferral(SearchResultEntry entry)
  {
    Set<String> values = asSetOfString(entry, OBJECTCLASS_ATTRIBUTE_TYPE_NAME);
    for (String value : values)
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/ConnectionWithControls.java
New file
@@ -0,0 +1,211 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2016 ForgeRock AS.
 */
package org.opends.guitools.controlpanel.browser;
import java.io.Closeable;
import org.forgerock.opendj.ldap.LdapException;
import org.forgerock.opendj.ldap.controls.ManageDsaITRequestControl;
import org.forgerock.opendj.ldap.controls.ServerSideSortRequestControl;
import org.forgerock.opendj.ldap.requests.AddRequest;
import org.forgerock.opendj.ldap.requests.DeleteRequest;
import org.forgerock.opendj.ldap.requests.ModifyDNRequest;
import org.forgerock.opendj.ldap.requests.ModifyRequest;
import org.forgerock.opendj.ldap.requests.Request;
import org.forgerock.opendj.ldap.requests.SearchRequest;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.forgerock.opendj.ldif.ConnectionEntryReader;
import org.forgerock.util.Reject;
import org.opends.admin.ads.util.ConnectionWrapper;
/**
 * Associates a {@link ConnectionWrapper} with the LDAP
 * {@link org.forgerock.opendj.ldap.controls.Control Control}s it should use when performing
 * operation.
 * <p>
 * The relevant controls are automatically added to the request when calling
 * {@link #add(AddRequest)}, {@link #delete(DeleteRequest)}, {@link #modify(ModifyRequest)},
 * {@link #modifyDN(ModifyDNRequest)}, {@link #search(SearchRequest)} or
 * {@link #searchSingleEntry(SearchRequest)}.
 */
public final class ConnectionWithControls implements Closeable
{
  private final ConnectionWrapper conn;
  private ServerSideSortRequestControl sortControl;
  private ManageDsaITRequestControl followReferralsControl;
  /**
   * Constructor.
   *
   * @param conn
   *          the connection wrapper
   * @param sortControl
   *          the sort control, may be {@code null}
   * @param followReferralsControl
   *          the manage dsa IT control, may be {@code null}
   */
  public ConnectionWithControls(ConnectionWrapper conn,
                                ServerSideSortRequestControl sortControl,
                                ManageDsaITRequestControl followReferralsControl)
  {
    this.conn = Reject.checkNotNull(conn);
    setRequestControls(sortControl, followReferralsControl);
  }
  /**
   * Returns the connection wrapper.
   * <p>
   * DO NOT USE TO PERFORM LDAP OPERATIONS!
   * <p>
   * This getter is only used to allow to query its state.
   *
   * @return the read-only connection wrapper.
   */
  public ConnectionWrapper getConnectionWrapper()
  {
    return conn;
  }
  /**
   * Sets the sort and manage dsa it controls to use when making LDAP operations.
   *
   * @param sortControl
   *          the sort control, may be {@code null}
   * @param followReferralsControl
   *          the manage dsa IT control, may be {@code null}
   */
  public void setRequestControls(
      ServerSideSortRequestControl sortControl,
      ManageDsaITRequestControl followReferralsControl)
  {
    this.sortControl = sortControl;
    this.followReferralsControl = followReferralsControl;
  }
  /**
   * Adds the sort and referral controls if needed.
   *
   * @param request
   *          the request
   */
  void addControls(Request request)
  {
    if (sortControl != null && request instanceof SearchRequest)
    {
      request.addControl(sortControl);
    }
    if (followReferralsControl != null)
    {
      request.addControl(followReferralsControl);
    }
  }
  /**
   * Searches a single entry.
   *
   * @param request
   *          the request
   * @return the non-{@code null} single SearchResultEntry
   * @throws LdapException
   *           if an error occurred.
   * @see org.forgerock.opendj.ldap.Connection#searchSingleEntry(SearchRequest)
   */
  public SearchResultEntry searchSingleEntry(SearchRequest request) throws LdapException
  {
    addControls(request);
    return conn.getConnection().searchSingleEntry(request);
  }
  /**
   * Searches using the provided request.
   *
   * @param request
   *          the request
   * @return a non-{@code null} {@link ConnectionEntryReader}
   * @see org.forgerock.opendj.ldap.Connection#search(SearchRequest)
   */
  public ConnectionEntryReader search(SearchRequest request)
  {
    addControls(request);
    return conn.getConnection().search(request);
  }
  /**
   * Adds with the provided request.
   *
   * @param request
   *          the request
   * @throws LdapException
   *           if an error occurred.
   * @see org.forgerock.opendj.ldap.Connection#add(AddRequest)
   */
  public void add(AddRequest request) throws LdapException
  {
    addControls(request);
    conn.getConnection().add(request);
  }
  /**
   * Deletes with the provided request.
   *
   * @param request
   *          the request
   * @throws LdapException
   *           if an error occurred.
   * @see org.forgerock.opendj.ldap.Connection#delete(DeleteRequest)
   */
  public void delete(DeleteRequest request) throws LdapException
  {
    addControls(request);
    conn.getConnection().delete(request);
  }
  /**
   * Modifies with the provided request.
   *
   * @param request
   *          the request
   * @throws LdapException
   *           if an error occurred.
   * @see org.forgerock.opendj.ldap.Connection#modify(ModifyRequest)
   */
  public void modify(ModifyRequest request) throws LdapException
  {
    addControls(request);
    conn.getConnection().modify(request);
  }
  /**
   * modifies a DN with the provided request.
   *
   * @param request
   *          the request
   * @throws LdapException
   *           if an error occurred.
   * @see org.forgerock.opendj.ldap.Connection#modifyDN(ModifyDNRequest)
   */
  public void modifyDN(ModifyDNRequest request) throws LdapException
  {
    addControls(request);
    conn.getConnection().modifyDN(request);
  }
  @Override
  public void close()
  {
    conn.close();
  }
}
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/LDAPConnectionPool.java
@@ -22,11 +22,12 @@
import java.util.HashMap;
import javax.naming.NamingException;
import javax.naming.ldap.Control;
import javax.net.ssl.KeyManager;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.SearchScope;
import org.forgerock.opendj.ldap.controls.ManageDsaITRequestControl;
import org.forgerock.opendj.ldap.controls.ServerSideSortRequestControl;
import org.opends.admin.ads.util.ApplicationTrustManager;
import org.opends.admin.ads.util.ConnectionWrapper;
import org.opends.admin.ads.util.PreferredConnection.Type;
@@ -70,30 +71,35 @@
  private ArrayList<ReferralAuthenticationListener> listeners;
  private Control[] requestControls = new Control[] {};
  private ServerSideSortRequestControl sortControl;
  private ManageDsaITRequestControl followReferralsControl;
  private ApplicationTrustManager trustManager;
  private int connectTimeout = CliConstants.DEFAULT_LDAP_CONNECT_TIMEOUT;
  /**
   * Returns <CODE>true</CODE> if the connection passed is registered in the
   * connection pool, <CODE>false</CODE> otherwise.
   * @param conn the connection.
   * @return <CODE>true</CODE> if the connection passed is registered in the
   * connection pool, <CODE>false</CODE> otherwise.
   * Returns whether the connection passed is registered in the connection pool.
   *
   * @param conn
   *          the connection.
   * @return {@code true} if the connection passed is registered in the connection pool,
   *         {@code false} otherwise.
   */
  public boolean isConnectionRegistered(ConnectionWrapper conn) {
    for (String key : connectionTable.keySet())
    {
      ConnectionRecord cr = connectionTable.get(key);
      if (cr.conn != null
          && cr.conn.getHostPort().equals(conn.getHostPort())
          && cr.conn.getBindDn().equals(conn.getBindDn())
          && cr.conn.getBindPassword().equals(conn.getBindPassword())
          && cr.conn.getConnectionType() == conn.getConnectionType())
      final ConnectionRecord cr = connectionTable.get(key);
      if (cr.conn != null)
      {
        final ConnectionWrapper c = cr.conn.getConnectionWrapper();
        if (c.getHostPort().equals(conn.getHostPort())
            && c.getBindDn().equals(conn.getBindDn())
            && c.getBindPassword().equals(conn.getBindPassword())
            && c.getConnectionType() == conn.getConnectionType())
      {
        return true;
      }
    }
    }
    return false;
  }
@@ -106,7 +112,7 @@
    LDAPURL url = makeLDAPUrl(conn);
    String key = makeKeyFromLDAPUrl(url);
    ConnectionRecord cr = new ConnectionRecord();
    cr.conn = conn;
    cr.conn = new ConnectionWithControls(conn, sortControl, followReferralsControl);
    cr.counter = 1;
    cr.disconnectAfterUse = false;
    connectionTable.put(key, cr);
@@ -155,8 +161,8 @@
   * @return a connection to the provided LDAP URL.
   * @throws NamingException if there was an error connecting.
   */
  public ConnectionWrapper getConnection(LDAPURL ldapUrl)
  throws NamingException {
  public ConnectionWithControls getConnection(LDAPURL ldapUrl) throws NamingException
  {
    String key = makeKeyFromLDAPUrl(ldapUrl);
    ConnectionRecord cr;
@@ -186,7 +192,6 @@
            registerAuth = true;
          }
          cr.conn = createLDAPConnection(ldapUrl, authRecord);
          cr.conn.getLdapContext().setRequestControls(requestControls);
          if (registerAuth)
          {
            authTable.put(key, authRecord);
@@ -208,20 +213,24 @@
  }
  /**
   * Sets the request controls to be used by the connections of this connection
   * pool.
   * @param ctls the request controls.
   * @throws NamingException if an error occurs updating the connections.
   * Sets the request controls to be used by the connections of this connection pool.
   *
   * @param sortControl
   *          the sort control.
   * @param followReferralsControl
   *          the manage dsa it control.
   */
  public synchronized void setRequestControls(Control[] ctls)
  throws NamingException
  public synchronized void setRequestControls(
      ServerSideSortRequestControl sortControl,
      ManageDsaITRequestControl followReferralsControl)
  {
    requestControls = ctls;
    this.sortControl = sortControl;
    this.followReferralsControl = followReferralsControl;
    for (ConnectionRecord cr : connectionTable.values())
    {
      if (cr.conn != null)
      {
        cr.conn.getLdapContext().setRequestControls(requestControls);
        cr.conn.setRequestControls(sortControl, followReferralsControl);
      }
    }
  }
@@ -234,7 +243,7 @@
   * @param conn
   *          the connection to be released.
   */
  public synchronized void releaseConnection(ConnectionWrapper conn) {
  public synchronized void releaseConnection(ConnectionWithControls conn) {
    String targetKey = null;
    ConnectionRecord targetRecord = null;
    synchronized(this) {
@@ -377,7 +386,8 @@
   * @return the key to be used in Maps for the provided connection record.
   */
  private static String makeKeyFromRecord(ConnectionRecord rec) {
    return (rec.conn.isLdaps() ? "LDAPS" : "LDAP") + ":" + rec.conn.getHostPort();
    ConnectionWrapper conn = rec.conn.getConnectionWrapper();
    return (conn.isLdaps() ? "LDAPS" : "LDAP") + ":" + conn.getHostPort();
  }
  /**
@@ -388,12 +398,13 @@
   * @return a connection.
   * @throws NamingException if an error occurs when connecting.
   */
  private ConnectionWrapper createLDAPConnection(LDAPURL ldapUrl, AuthRecord ar) throws NamingException
  private ConnectionWithControls createLDAPConnection(LDAPURL ldapUrl, AuthRecord ar) throws NamingException
  {
    final HostPort hostPort = new HostPort(ldapUrl.getHost(), ldapUrl.getPort());
    final Type connectiontype = isSecureLDAPUrl(ldapUrl) ? LDAPS : LDAP;
    return new ConnectionWrapper(hostPort, connectiontype, ar.dn, ar.password,
    final ConnectionWrapper conn = new ConnectionWrapper(hostPort, connectiontype, ar.dn, ar.password,
        getConnectTimeout(), getTrustManager(), getKeyManager());
    return new ConnectionWithControls(conn, sortControl, followReferralsControl);
  }
  /**
@@ -496,7 +507,6 @@
        null, // No filter
        null); // No extensions
  }
}
/** A structure representing authentication data. */
@@ -507,7 +517,7 @@
/** A structure representing an active connection. */
class ConnectionRecord {
  ConnectionWrapper conn;
  ConnectionWithControls conn;
  int counter;
  boolean disconnectAfterUse;
}
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/NodeRefresher.java
@@ -36,6 +36,7 @@
import org.forgerock.i18n.LocalizedIllegalArgumentException;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.Filter;
import org.forgerock.opendj.ldap.LdapException;
import org.forgerock.opendj.ldap.RDN;
import org.forgerock.opendj.ldap.ResultCode;
@@ -187,7 +188,7 @@
   * BrowserController is following referrals and the local entry otherwise.
   */
  public SearchResultEntry getDisplayedEntry() {
    if (controller.getFollowReferrals() && remoteEntry != null)
    if (controller.isFollowReferrals() && remoteEntry != null)
    {
      return remoteEntry;
    }
@@ -204,7 +205,7 @@
   * otherwise.
   */
  public LDAPURL getDisplayedUrl() {
    if (controller.getFollowReferrals() && remoteUrl != null)
    if (controller.isFollowReferrals() && remoteUrl != null)
    {
      return remoteUrl;
    }
@@ -235,7 +236,7 @@
        runReadLocalEntry();
      }
      if (!isInFinalState()) {
        if (controller.getFollowReferrals() && isReferralEntry(localEntry)) {
        if (controller.isFollowReferrals() && isReferralEntry(localEntry)) {
          changeStateTo(State.SOLVING_REFERRAL);
          runSolveReferral();
        }
@@ -302,12 +303,12 @@
   * @throws IOException
   *           if a problem occurred.
   */
  private void searchForCustomFilter(BasicNode node, ConnectionWrapper conn) throws IOException
  private void searchForCustomFilter(BasicNode node, ConnectionWithControls conn) throws IOException
  {
    SearchRequest request =
        newSearchRequest(node.getDN().toString(), WHOLE_SUBTREE, controller.getFilter(), NO_ATTRIBUTES)
        newSearchRequest(node.getDN(), WHOLE_SUBTREE, controller.getFilter(), NO_ATTRIBUTES)
        .setSizeLimit(1);
    try (ConnectionEntryReader s = conn.getConnection().search(request))
    try (ConnectionEntryReader s = conn.search(request))
    {
      if (!s.hasNext())
      {
@@ -342,11 +343,11 @@
   * @param conn the connection to be used.
   * @throws IOException if a problem occurred.
   */
  private void searchForCustomFilter(String dn, ConnectionWrapper conn) throws IOException
  private void searchForCustomFilter(DN dn, ConnectionWithControls conn) throws IOException
  {
    SearchRequest request = newSearchRequest(dn, WHOLE_SUBTREE, controller.getFilter())
        .setSizeLimit(1);
    try (ConnectionEntryReader entryReader = conn.getConnection().search(request))
    try (ConnectionEntryReader entryReader = conn.search(request))
    {
      if (!entryReader.hasNext())
      {
@@ -375,7 +376,7 @@
  /** Read the local entry associated to the current node. */
  private void runReadLocalEntry() throws SearchAbandonException {
    BasicNode node = getNode();
    ConnectionWrapper conn = null;
    ConnectionWithControls conn = null;
    try {
      conn = controller.findConnectionForLocalEntry(node);
@@ -386,15 +387,10 @@
          searchForCustomFilter(node, conn);
        }
        String filter = controller.getObjectSearchFilter();
        SearchRequest request =
            newSearchRequest(node.getDN().toString(), BASE_OBJECT, filter, controller.getAttrsForRedSearch())
            .setSizeLimit(controller.getMaxChildren());
        localEntry = conn.getConnection().searchSingleEntry(request);
        if (localEntry == null) {
          /* Not enough rights to read the entry or the entry simply does not exist */
          throw newLdapException(ResultCode.NO_SUCH_OBJECT, "Can't find entry: " + node.getDN());
        }
            newSearchRequest(node.getDN(), BASE_OBJECT, controller.getObjectSearchFilter(), controller
                .getAttrsForRedSearch()).setSizeLimit(controller.getMaxChildren());
        localEntry = conn.searchSingleEntry(request);
        throwAbandonIfNeeded(null);
      } else {
          changeStateTo(State.FINISHED);
@@ -447,40 +443,40 @@
    LDAPConnectionPool connectionPool = controller.getConnectionPool();
    LDAPURL url = null;
    SearchResultEntry entry = null;
    String remoteDn = null;
    DN remoteDn = null;
    Exception lastException = null;
    Object lastExceptionArg = null;
    int i = 0;
    while (i < referral.length && entry == null)
    {
      ConnectionWrapper conn = null;
      ConnectionWithControls conn = null;
      try {
        url = LDAPURL.decode(referral[i], false);
        if (url.getHost() == null)
        {
          // Use the local server connection.
          ConnectionWrapper userConn = controller.getUserDataConnection();
          ConnectionWrapper userConn = controller.getUserDataConnection().getConnectionWrapper();
          HostPort hostPort = userConn.getHostPort();
          url.setHost(hostPort.getHost());
          url.setPort(hostPort.getPort());
          url.setScheme(userConn.isLdaps() ? "ldaps" : "ldap");
        }
        conn = connectionPool.getConnection(url);
        remoteDn = url.getRawBaseDN();
        remoteDn = DN.valueOf(url.getRawBaseDN());
        if (remoteDn == null || "".equals(remoteDn))
        {
          /* The referral has not a target DN specified: we
             have to use the DN of the entry that contains the
             referral... */
          if (remoteEntry != null) {
            remoteDn = remoteEntry.getName().toString();
            remoteDn = remoteEntry.getName();
          } else {
            remoteDn = localEntry.getName().toString();
            remoteDn = localEntry.getName();
          }
          /* We have to recreate the url including the target DN we are using */
          url = new LDAPURL(url.getScheme(), url.getHost(), url.getPort(),
              remoteDn, url.getAttributes(), url.getScope(), url.getRawFilter(),
              remoteDn.toString(), url.getAttributes(), url.getScope(), url.getRawFilter(),
                 url.getExtensions());
        }
        if (useCustomFilter() && url.getScope() == SearchScope.BASE_OBJECT)
@@ -489,11 +485,12 @@
          searchForCustomFilter(remoteDn, conn);
        }
        String filter = getFilter(url);
        Filter filter = getFilter(url);
        SearchRequest request = newSearchRequest(remoteDn, url.getScope(), filter, controller.getAttrsForBlackSearch())
            .setSizeLimit(controller.getMaxChildren());
        try (ConnectionEntryReader sr = conn.getConnection().search(request))
        SearchRequest request =
            newSearchRequest(remoteDn, url.getScope(), filter, controller.getAttrsForBlackSearch()).setSizeLimit(
                controller.getMaxChildren());
        try (ConnectionEntryReader sr = conn.search(request))
        {
          boolean found = false;
          while (sr.hasNext())
@@ -607,12 +604,11 @@
   */
  private void runDetectChildrenManually() throws SearchAbandonException {
    BasicNode parentNode = getNode();
    ConnectionWrapper conn = null;
    ConnectionWithControls conn = 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.
      // Send an LDAP search
      conn = controller.findConnectionForDisplayedEntry(parentNode);
      SearchRequest request = newSearchRequest(
              controller.findBaseDNForChildEntries(parentNode),
@@ -620,7 +616,7 @@
              controller.getChildSearchFilter(),
              NO_ATTRIBUTES)
          .setSizeLimit(1);
      try (ConnectionEntryReader searchResults = conn.getConnection().search(request))
      try (ConnectionEntryReader searchResults = conn.search(request))
      {
        throwAbandonIfNeeded(null);
        // Check if parentNode has children
@@ -676,32 +672,24 @@
   * @throws SearchAbandonException if an error occurs.
   */
  private void runSearchChildren() throws SearchAbandonException {
    ConnectionWrapper conn = null;
    ConnectionWithControls conn = null;
    BasicNode parentNode = getNode();
    parentNode.setSizeLimitReached(false);
    try {
      // Send an LDAP search
      conn = controller.findConnectionForDisplayedEntry(parentNode);
      String parentDn = controller.findBaseDNForChildEntries(parentNode);
      int parentComponents;
      try
      {
        DN dn = DN.valueOf(parentDn);
        parentComponents = dn.size();
      }
      catch (Throwable t)
      {
        throw new RuntimeException("Error decoding dn: "+parentDn+" . "+t,
            t);
      }
      DN parentDn = controller.findBaseDNForChildEntries(parentNode);
      int parentComponents = parentDn.size();
      SearchScope scope = useCustomFilter() ? WHOLE_SUBTREE : SINGLE_LEVEL;
      SearchRequest request =
          newSearchRequest(parentDn, scope, controller.getChildSearchFilter(), controller.getAttrsForRedSearch())
      SearchRequest request = newSearchRequest(
          parentDn,
          useCustomFilter() ? WHOLE_SUBTREE : SINGLE_LEVEL,
          controller.getChildSearchFilter(),
          controller.getAttrsForRedSearch())
              .setSizeLimit(controller.getMaxChildren());
      try (ConnectionEntryReader entries = conn.getConnection().search(request))
      try (ConnectionEntryReader entries = conn.search(request))
      {
        while (entries.hasNext())
        {
@@ -728,7 +716,7 @@
              boolean mustAddParent = mustAddParent(parentToAddDN) && mustAddParent2(parentToAddDN);
              if (mustAddParent)
              {
                SearchResultEntry parentResult = searchManuallyEntry(conn, parentToAddDN.toString());
                SearchResultEntry parentResult = searchManuallyEntry(conn, parentToAddDN);
                childEntries.add(parentResult);
              }
            }
@@ -829,13 +817,13 @@
   * @param dn the DN of the entry to be searched.
   * @throws NamingException if an error occurs.
   */
  private SearchResultEntry searchManuallyEntry(ConnectionWrapper conn, String dn) throws IOException
  private SearchResultEntry searchManuallyEntry(ConnectionWithControls conn, DN dn) throws IOException
  {
    SearchRequest request =
        newSearchRequest(dn, BASE_OBJECT, controller.getObjectSearchFilter(), controller.getAttrsForRedSearch())
        .setSizeLimit(controller.getMaxChildren());
    SearchResultEntry sr = conn.getConnection().searchSingleEntry(request);
    SearchResultEntry sr = conn.searchSingleEntry(request);
    sr.setName(dn);
    return sr;
  }
@@ -921,14 +909,10 @@
   *          the LDAP URL.
   * @return the filter.
   */
  private String getFilter(LDAPURL url)
  private Filter getFilter(LDAPURL url)
  {
    String filter = url.getRawFilter();
    if (filter == null)
    {
      filter = controller.getObjectSearchFilter();
    }
    return filter;
    return filter != null ? Filter.valueOf(filter) : controller.getObjectSearchFilter();
  }
  /**
@@ -941,31 +925,26 @@
   * is actually an entry in the same server as the local entry but above in the
   * DIT).
   */
  private void checkLoopInReferral(LDAPURL url,
      String referral) throws SearchAbandonException
  private void checkLoopInReferral(LDAPURL url, String referral) throws SearchAbandonException
  {
    boolean checkSucceeded = true;
    try
    {
      if (url.getBaseDN().isSuperiorOrEqualTo(getNode().getDN()))
      {
        HostPort urlHostPort = new HostPort(url.getHost(), url.getPort());
        checkSucceeded = urlHostPort.equals(controller.getConfigurationConnection().getHostPort());
        if (checkSucceeded)
        {
          checkSucceeded = urlHostPort.equals(controller.getUserDataConnection().getHostPort());
        }
      }
    }
    catch (OpenDsException odse)
    {
      // Ignore
    }
        HostPort hp = new HostPort(url.getHost(), url.getPort());
        boolean checkSucceeded =
            hp.equals(controller.getConfigurationConnection().getConnectionWrapper().getHostPort())
            && hp.equals(controller.getUserDataConnection().getConnectionWrapper().getHostPort());
    if (!checkSucceeded)
    {
      throw new SearchAbandonException(
          State.FAILED, new ReferralLimitExceededException(
              ERR_CTRL_PANEL_REFERRAL_LOOP.get(url.getRawBaseDN())), referral);
          Exception cause = new ReferralLimitExceededException(ERR_CTRL_PANEL_REFERRAL_LOOP.get(url.getRawBaseDN()));
          throw new SearchAbandonException(State.FAILED, cause, referral);
        }
      }
    }
    catch (OpenDsException ignore)
    {
      // Ignore
    }
  }
}
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/AddToGroupTask.java
@@ -37,7 +37,6 @@
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.Filter;
import org.forgerock.opendj.ldap.Modification;
import org.forgerock.opendj.ldap.requests.ModifyRequest;
import org.forgerock.opendj.ldap.requests.SearchRequest;
@@ -207,7 +206,7 @@
  private void addModifications(DN groupDn, Set<DN> dns, ModifyRequest modRequest) throws IOException
  {
    // Search for the group entry
    SearchRequest searchRequest = newSearchRequest(groupDn, BASE_OBJECT, Filter.valueOf(ALL_OBJECTS_FILTER),
    SearchRequest searchRequest = newSearchRequest(groupDn, BASE_OBJECT, ALL_OBJECTS_FILTER,
        OBJECTCLASS_ATTRIBUTE_TYPE_NAME,
        ATTR_MEMBER,
        ATTR_UNIQUE_MEMBER);
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/DeleteEntryTask.java
@@ -47,6 +47,7 @@
import org.forgerock.opendj.ldif.ConnectionEntryReader;
import org.opends.admin.ads.util.ConnectionWrapper;
import org.opends.guitools.controlpanel.browser.BrowserController;
import org.opends.guitools.controlpanel.browser.ConnectionWithControls;
import org.opends.guitools.controlpanel.datamodel.BackendDescriptor;
import org.opends.guitools.controlpanel.datamodel.BaseDNDescriptor;
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
@@ -187,7 +188,7 @@
        DN dn = node.getDN();
        if (!isAlreadyDeleted(alreadyDeleted, dn))
        {
          ConnectionWrapper conn = controller.findConnectionForDisplayedEntry(node);
          ConnectionWithControls conn = controller.findConnectionForDisplayedEntry(node);
          useAdminCtx = controller.isConfigurationNode(node);
          if (node.hasSubOrdinates())
          {
@@ -279,7 +280,7 @@
    }
  }
  private void deleteSubtreeRecursively(ConnectionWrapper conn, DN dnToRemove, TreePath path,
  private void deleteSubtreeRecursively(ConnectionWithControls conn, DN dnToRemove, TreePath path,
      List<BrowserNodeInfo> toNotify) throws NamingException, IOException, DirectoryException
  {
    lastDn = dnToRemove;
@@ -313,7 +314,7 @@
    String filter = "(|(objectClass=*)(objectclass=ldapsubentry))";
    SearchRequest request = newSearchRequest(dnToRemove, SINGLE_LEVEL, Filter.valueOf(filter), NO_ATTRIBUTES);
    try (ConnectionEntryReader entryDNs = conn.getConnection().search(request))
    try (ConnectionEntryReader entryDNs = conn.search(request))
    {
      while (entryDNs.hasNext())
      {
@@ -331,7 +332,7 @@
    try
    {
      conn.getConnection().delete(dnToRemove.toString());
      conn.delete(newDeleteRequest(dnToRemove));
      if (path != null)
      {
        toNotify.add(controller.getNodeInfoFromPath(path));
@@ -372,8 +373,8 @@
    }
  }
  private void deleteSubtreeWithControl(ConnectionWrapper conn, DN dn, TreePath path, List<BrowserNodeInfo> toNotify)
      throws LdapException, NamingException
  private void deleteSubtreeWithControl(ConnectionWithControls conn, DN dn, TreePath path,
      List<BrowserNodeInfo> toNotify) throws LdapException, NamingException
  {
    lastDn = dn;
    long t = System.currentTimeMillis();
@@ -395,11 +396,12 @@
                    ColorAndFontConstants.defaultFont)));
      }
    });
    //  Use a copy of the dir context since we are using an specific
    // Use a copy of the connection since we are using a specific
    // control to delete the subtree and this can cause
    // synchronization problems when the tree is refreshed.
    ControlPanelInfo info = getInfo();
    try (ConnectionWrapper conn1 = cloneConnectionWrapper(conn, info.getConnectTimeout(), info.getTrustManager(), null))
    try (ConnectionWrapper conn1 =
        cloneConnectionWrapper(conn.getConnectionWrapper(), info.getConnectTimeout(), info.getTrustManager(), null))
    {
      DeleteRequest request = newDeleteRequest(dn).addControl(SubtreeDeleteRequestControl.newControl(true));
      conn1.getConnection().delete(request);
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/ModifyEntryTask.java
@@ -43,8 +43,8 @@
import org.forgerock.opendj.ldap.RDN;
import org.forgerock.opendj.ldap.requests.ModifyRequest;
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.opends.admin.ads.util.ConnectionWrapper;
import org.opends.guitools.controlpanel.browser.BrowserController;
import org.opends.guitools.controlpanel.browser.ConnectionWithControls;
import org.opends.guitools.controlpanel.datamodel.BackendDescriptor;
import org.opends.guitools.controlpanel.datamodel.BaseDNDescriptor;
import org.opends.guitools.controlpanel.datamodel.CannotRenameException;
@@ -205,7 +205,7 @@
    try
    {
      BasicNode node = (BasicNode)treePath.getLastPathComponent();
      ConnectionWrapper conn = controller.findConnectionForDisplayedEntry(node);
      ConnectionWithControls conn = controller.findConnectionForDisplayedEntry(node);
      useAdminCtx = controller.isConfigurationNode(node);
      if (!mustRename)
      {
@@ -224,7 +224,7 @@
            }
          });
          conn.getConnection().modify(newModifyRequest0(oldEntry.getName(), modifications));
          conn.modify(newModifyRequest0(oldEntry.getName(), modifications));
          SwingUtilities.invokeLater(new Runnable()
          {
@@ -295,7 +295,7 @@
   * @throws CannotRenameException if we cannot perform the modification.
   * @throws LdapException if an error performing the modification occurs.
   */
  private void modifyAndRename(ConnectionWrapper conn, final DN oldDN,
  private void modifyAndRename(ConnectionWithControls conn, final DN oldDN,
      org.forgerock.opendj.ldap.Entry originalEntry,
      final Entry newEntry, final List<Modification> originalMods)
      throws CannotRenameException, LdapException
@@ -325,7 +325,7 @@
      }
    });
    conn.getConnection().modifyDN(newModifyDNRequest(oldDn, newRDN));
    conn.modifyDN(newModifyDNRequest(oldDn, newRDN));
    final TreePath[] newPath = {null};
@@ -361,7 +361,7 @@
        }
      });
      conn.getConnection().modify(newModifyRequest0(newEntry.getName(), originalMods));
      conn.modify(newModifyRequest0(newEntry.getName(), originalMods));
      SwingUtilities.invokeLater(new Runnable()
      {
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/NewEntryTask.java
@@ -16,6 +16,7 @@
 */
package org.opends.guitools.controlpanel.task;
import static org.forgerock.opendj.ldap.requests.Requests.*;
import static org.opends.messages.AdminToolMessages.*;
import java.util.ArrayList;
@@ -32,6 +33,7 @@
import org.forgerock.opendj.ldap.DN;
import org.opends.admin.ads.util.ConnectionWrapper;
import org.opends.guitools.controlpanel.browser.BrowserController;
import org.opends.guitools.controlpanel.browser.ConnectionWithControls;
import org.opends.guitools.controlpanel.datamodel.BackendDescriptor;
import org.opends.guitools.controlpanel.datamodel.BaseDNDescriptor;
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
@@ -152,33 +154,22 @@
    try
    {
      ConnectionWrapper conn;
      if (parentNode != null)
      {
        conn = controller.findConnectionForDisplayedEntry(parentNode);
        ConnectionWithControls conn = controller.findConnectionForDisplayedEntry(parentNode);
        useAdminCtx = controller.isConfigurationNode(parentNode);
        printProgressCreatingEntry();
        conn.add(newAddRequest(Converters.from(newEntry)));
      }
      else
      {
        conn = getInfo().getConnection();
        ConnectionWrapper conn = getInfo().getConnection();
        useAdminCtx = true;
      }
      SwingUtilities.invokeLater(new Runnable()
      {
        @Override
        public void run()
        {
          printEquivalentCommand();
          getProgressDialog().appendProgressHtml(
              Utilities.getProgressWithPoints(
                  INFO_CTRL_PANEL_CREATING_ENTRY.get(dn),
                  ColorAndFontConstants.progressFont));
        }
      });
        printProgressCreatingEntry();
      conn.getConnection().add(Converters.from(newEntry));
      }
      SwingUtilities.invokeLater(new Runnable()
      {
@@ -227,6 +218,22 @@
    }
  }
  private void printProgressCreatingEntry()
  {
    SwingUtilities.invokeLater(new Runnable()
    {
      @Override
      public void run()
      {
        printEquivalentCommand();
        getProgressDialog().appendProgressHtml(
            Utilities.getProgressWithPoints(
                INFO_CTRL_PANEL_CREATING_ENTRY.get(dn),
                ColorAndFontConstants.progressFont));
      }
    });
  }
  /** Prints the equivalent command-line in the progress dialog. */
  private void printEquivalentCommand()
  {
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/ResetUserPasswordTask.java
@@ -38,6 +38,7 @@
import org.forgerock.opendj.ldif.ConnectionEntryReader;
import org.opends.admin.ads.util.ConnectionWrapper;
import org.opends.guitools.controlpanel.browser.BrowserController;
import org.opends.guitools.controlpanel.browser.ConnectionWithControls;
import org.opends.guitools.controlpanel.datamodel.BackendDescriptor;
import org.opends.guitools.controlpanel.datamodel.BaseDNDescriptor;
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
@@ -86,10 +87,10 @@
    try
    {
      ConnectionWrapper conn = controller.findConnectionForDisplayedEntry(node);
      ConnectionWithControls conn = controller.findConnectionForDisplayedEntry(node);
      if (conn != null && isBoundAs(dn, conn))
      {
        currentPassword = conn.getBindPassword().toCharArray();
        currentPassword = conn.getConnectionWrapper().getBindPassword().toCharArray();
      }
    }
    catch (Throwable t)
@@ -225,16 +226,16 @@
   * @param conn the connection that we are using to modify the password.
   * @return {@code true} if we are bound using the provided entry.
   */
  private boolean isBoundAs(DN dn, ConnectionWrapper conn)
  private boolean isBoundAs(DN dn, ConnectionWithControls conn)
  {
    final DN bindDN = conn.getBindDn();
    final DN bindDN = conn.getConnectionWrapper().getBindDn();
    boolean isBoundAs = dn.equals(bindDN);
    if (!isBoundAs)
    {
      String attrName = ATTR_ROOTDN_ALTERNATE_BIND_DN;
      Filter filter = Filter.valueOf("(|(objectClass=*)(objectclass=ldapsubentry))");
      SearchRequest request = newSearchRequest(dn, BASE_OBJECT, filter, attrName);
      try (ConnectionEntryReader entries = conn.getConnection().search(request))
      try (ConnectionEntryReader entries = conn.search(request))
      {
        while (entries.hasNext())
        {
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/AbstractBrowseEntriesPanel.java
@@ -18,6 +18,7 @@
import static com.forgerock.opendj.cli.Utils.*;
import static org.opends.guitools.controlpanel.browser.BrowserController.*;
import static org.opends.messages.AdminToolMessages.*;
import static org.opends.messages.QuickSetupMessages.*;
@@ -69,13 +70,14 @@
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.LocalizableMessageBuilder;
import org.forgerock.i18n.LocalizedIllegalArgumentException;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.forgerock.opendj.ldap.Filter;
import org.opends.admin.ads.util.ApplicationTrustManager;
import org.opends.admin.ads.util.ConnectionWrapper;
import org.opends.guitools.controlpanel.browser.BrowserController;
import org.opends.guitools.controlpanel.browser.ConnectionWithControls;
import org.opends.guitools.controlpanel.datamodel.BackendDescriptor;
import org.opends.guitools.controlpanel.datamodel.BaseDNDescriptor;
import org.opends.guitools.controlpanel.datamodel.CategorizedComboBoxElement;
@@ -96,10 +98,6 @@
import org.opends.quicksetup.UserDataCertificateException;
import org.opends.quicksetup.ui.CertificateDialog;
import org.opends.quicksetup.util.UIKeyStore;
import org.opends.server.protocols.ldap.LDAPFilter;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.LDAPException;
import org.opends.server.types.SearchFilter;
import org.opends.server.util.ServerConstants;
/**
@@ -614,14 +612,14 @@
    {
      errors.add(INFO_CTRL_PANEL_NO_BASE_DN_SELECTED.get());
    }
    String filterValue = getFilter();
    Filter filterValue = null;
    try
    {
      LDAPFilter.decode(filterValue);
      filterValue = getFilter();
    }
    catch (LDAPException le)
    catch (LocalizedIllegalArgumentException e)
    {
      errors.add(INFO_CTRL_PANEL_INVALID_FILTER_DETAILS.get(le.getMessageObject()));
      errors.add(INFO_CTRL_PANEL_INVALID_FILTER_DETAILS.get(e.getMessageObject()));
      setPrimaryInvalid(lFilter);
    }
    if (errors.isEmpty())
@@ -672,7 +670,7 @@
          else
          {
            BasicNode rootNode = (BasicNode) controller.getTree().getModel().getRoot();
            if (controller.findChildNode(rootNode, theDN) == -1)
            if (findChildNode(rootNode, theDN) == -1)
            {
              controller.addNodeUnderRoot(theDN);
            }
@@ -710,7 +708,7 @@
   *
   * @return the LDAP filter built based in the parameters provided by the user.
   */
  private String getFilter()
  private Filter getFilter()
  {
    String filterText = filter.getText();
    if (filterText.length() == 0)
@@ -727,39 +725,41 @@
        return BrowserController.ALL_OBJECTS_FILTER;
      }
      return filterText;
      return Filter.valueOf(filterText);
    }
    else if (USER_FILTER.equals(attr))
    {
      if ("*".equals(filterText))
      {
        return "(objectClass=person)";
        return Filter.valueOf("(objectClass=person)");
      }
      return "(&(objectClass=person)(|" + "(cn=" + filterText + ")(sn=" + filterText + ")(uid=" + filterText + ")))";
      return Filter.valueOf(
          "(&(objectClass=person)"
              + "(|(cn=" + filterText + ")"
                  + "(sn=" + filterText + ")"
                  + "(uid=" + filterText + ")))");
    }
    else if (GROUP_FILTER.equals(attr))
    {
      if ("*".equals(filterText))
      {
        return "(|(objectClass=groupOfUniqueNames)(objectClass=groupOfURLs))";
        return Filter.valueOf("(|(objectClass=groupOfUniqueNames)(objectClass=groupOfURLs))");
      }
      return "(&(|(objectClass=groupOfUniqueNames)(objectClass=groupOfURLs))" + "(cn=" + filterText + "))";
      return Filter.valueOf(
          "(&(|(objectClass=groupOfUniqueNames)(objectClass=groupOfURLs))" + "(cn=" + filterText + "))");
    }
    else if (attr != null)
    {
      try
      {
        return new LDAPFilter(SearchFilter.createFilterFromString("(" + attr + "=" + filterText + ")")).toString();
        return Filter.valueOf("(" + attr + "=" + filterText + ")");
      }
      catch (DirectoryException de)
      catch (LocalizedIllegalArgumentException ignored)
      {
        // Try this alternative:
        AttributeType attrType =
            getInfo().getServerDescriptor().getSchema().getAttributeType(attr.toString().toLowerCase());
        ByteString filterBytes = ByteString.valueOfUtf8(filterText);
        return new LDAPFilter(SearchFilter.createEqualityFilter(attrType, filterBytes)).toString();
        return Filter.equality(attr.toString(), filterText);
      }
    }
    else
@@ -835,7 +835,7 @@
                }
                else
                {
                  int index = controller.findChildNode(rootNode, baseDN);
                  int index = findChildNode(rootNode, baseDN);
                  if (index >= 0)
                  {
                    TreeNode node = rootNode.getChildAt(index);
@@ -857,7 +857,7 @@
            }
          }
        }
        if (isSubordinate && controller.findChildNode(rootNode, theDN) == -1)
        if (isSubordinate && findChildNode(rootNode, theDN) == -1)
        {
          controller.addNodeUnderRoot(theDN);
        }
@@ -1189,8 +1189,8 @@
        try
        {
          ConnectionWrapper conn = getInfo().getConnection();
          ConnectionWrapper conn1 = controller.getConfigurationConnection();
          boolean setConnection = conn != conn1;
          ConnectionWithControls conn1 = controller.getConfigurationConnection();
          boolean setConnection = conn1 == null || conn1.getConnectionWrapper() != conn;
          updateNumSubordinateHacker(desc);
          if (setConnection)
          {
@@ -1199,24 +1199,16 @@
              ConnectionWrapper connUserData = createUserDataDirContext(conn.getBindDn(), conn.getBindPassword());
              getInfo().setUserDataDirContext(connUserData);
            }
            final NamingException[] fNe = { null };
            Runnable runnable = new Runnable()
            {
              @Override
              public void run()
              {
                try
                {
                  ControlPanelInfo info = getInfo();
                  controller.setConnections(
                      info.getServerDescriptor(), info.getConnection(), info.getUserDataDirContext());
                  applyButtonClicked();
                }
                catch (NamingException ne)
                {
                  fNe[0] = ne;
                }
              }
            };
            if (!SwingUtilities.isEventDispatchThread())
            {
@@ -1230,11 +1222,6 @@
            {
              runnable.run();
            }
            if (fNe[0] != null)
            {
              throw fNe[0];
            }
          }
          displayNodes = true;
        }
@@ -1341,7 +1328,7 @@
              if (!added && !displayAll)
              {
                BasicNode rootNode = (BasicNode) controller.getTree().getModel().getRoot();
                if (controller.findChildNode(rootNode, theDN) == -1)
                if (findChildNode(rootNode, theDN) == -1)
                {
                  controller.addNodeUnderRoot(theDN);
                }
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/AbstractNewEntryPanel.java
@@ -25,6 +25,7 @@
import javax.swing.SwingUtilities;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.ldap.DN;
import org.opends.guitools.controlpanel.browser.BrowserController;
import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
import org.opends.guitools.controlpanel.task.NewEntryTask;
@@ -156,7 +157,7 @@
        // Unexpected error: getEntry() should work after calling checkSyntax
        throw new RuntimeException("Unexpected error: "+t, t);
      }
      String dn = entry.getName().toString();
      DN dn = entry.getName();
      // Checking for the existence of an entry is fast enough so we can do
      // it on the event thread.
      if (entryExists(dn))
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/AddToGroupPanel.java
@@ -43,6 +43,9 @@
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.LocalizedIllegalArgumentException;
import org.forgerock.opendj.ldap.DN;
import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
import org.opends.guitools.controlpanel.task.AddToGroupTask;
import org.opends.guitools.controlpanel.task.Task;
@@ -50,9 +53,6 @@
import org.opends.guitools.controlpanel.ui.nodes.DndBrowserNodes;
import org.opends.guitools.controlpanel.util.BackgroundTask;
import org.opends.guitools.controlpanel.util.Utilities;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.LocalizedIllegalArgumentException;
import org.forgerock.opendj.ldap.DN;
import org.opends.server.util.ServerConstants;
/** The dialog that is displayed when we want to add entries to a set of groups. */
@@ -327,24 +327,23 @@
    String[] grs = groups.getText().split("\n");
    boolean oneGroupDefined = false;
    for (String groupDn : grs)
    for (String groupDnStr : grs)
    {
      groupDn = groupDn.trim();
      if (groupDn.length() > 0)
      groupDnStr = groupDnStr.trim();
      if (groupDnStr.length() > 0)
      {
        try
        {
          DN.valueOf(groupDn);
          if (!entryExists(groupDn))
          DN groupDN = DN.valueOf(groupDnStr);
          if (!entryExists(groupDN))
          {
            errors.add(
                ERR_CTRL_PANEL_GROUP_COULD_NOT_BE_FOUND.get(groupDn));
            errors.add(ERR_CTRL_PANEL_GROUP_COULD_NOT_BE_FOUND.get(groupDnStr));
          }
          else if (!hasObjectClass(groupDn, ServerConstants.OC_GROUP_OF_NAMES,
          else if (!hasObjectClass(groupDN, ServerConstants.OC_GROUP_OF_NAMES,
            ServerConstants.OC_GROUP_OF_ENTRIES,
            ServerConstants.OC_GROUP_OF_UNIQUE_NAMES))
          {
            errors.add(ERR_CTRL_PANEL_NOT_A_STATIC_GROUP.get(groupDn));
            errors.add(ERR_CTRL_PANEL_NOT_A_STATIC_GROUP.get(groupDnStr));
          }
          else
          {
@@ -353,7 +352,7 @@
        }
        catch (LocalizedIllegalArgumentException e)
        {
          errors.add(INFO_CTRL_PANEL_INVALID_DN_DETAILS.get(groupDn, e.getMessageObject()));
          errors.add(INFO_CTRL_PANEL_INVALID_DN_DETAILS.get(groupDnStr, e.getMessageObject()));
        }
      }
    }
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/BrowseEntriesPanel.java
@@ -43,7 +43,6 @@
import java.util.LinkedHashSet;
import javax.naming.InterruptedNamingException;
import javax.naming.NamingException;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
@@ -66,7 +65,7 @@
import org.forgerock.opendj.ldap.Entry;
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.forgerock.opendj.ldap.schema.ObjectClass;
import org.opends.admin.ads.util.ConnectionWrapper;
import org.opends.guitools.controlpanel.browser.ConnectionWithControls;
import org.opends.guitools.controlpanel.browser.NodeRefresher;
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
@@ -503,7 +502,7 @@
    if (node != null)
    {
      DN dn;
      if (controller.getFollowReferrals() &&
      if (controller.isFollowReferrals() &&
          node.getReferral() != null &&
          node.getRemoteUrl() == null &&
          node.getError() != null &&
@@ -514,7 +513,7 @@
        entryPane.referralSolveError(node.getDN(), node.getReferral(), node.getError());
        dn = null;
      }
      else if (controller.getFollowReferrals() && node.getRemoteUrl() != null)
      else if (controller.isFollowReferrals() && node.getRemoteUrl() != null)
      {
        dn = DN.valueOf(node.getRemoteUrl().getRawBaseDN());
      }
@@ -527,11 +526,10 @@
      {
        try
        {
          ConnectionWrapper conn = controller.findConnectionForDisplayedEntry(node);
          ConnectionWithControls conn = controller.findConnectionForDisplayedEntry(node);
          LDAPEntryReader reader = new LDAPEntryReader(dn, conn);
          reader.addEntryReadListener(entryPane);
          // Required to update the browser controller properly if the entry is
          // deleted.
          // Required to update the browser controller properly if the entry is deleted.
          entryPane.setTreePath(path);
          stopCurrentReader();
          startReader(reader);
@@ -1246,41 +1244,21 @@
      menu.add(sortUserData);
      menu.add(followReferrals);
      sortUserData.setSelected(entryPane.getController().isSorted());
      followReferrals.setSelected(
          entryPane.getController().getFollowReferrals());
      followReferrals.setSelected(entryPane.getController().isFollowReferrals());
      sortUserData.addActionListener(new ActionListener()
      {
        @Override
        public void actionPerformed(ActionEvent ev)
        {
          try
          {
            entryPane.getController().setSorted(sortUserData.isSelected());
          }
          catch (NamingException ne)
          {
            // Bug
            System.err.println("Unexpected error updating sorting.");
            ne.printStackTrace();
          }
        }
      });
      followReferrals.addActionListener(new ActionListener()
      {
        @Override
        public void actionPerformed(ActionEvent ev)
        {
          try
          {
            entryPane.getController().setFollowReferrals(
                followReferrals.isSelected());
          }
          catch (NamingException ne)
          {
            // Bug
            System.err.println("Unexpected error updating referral state.");
            ne.printStackTrace();
          }
          entryPane.getController().setFollowReferrals(followReferrals.isSelected());
        }
      });
      // Add the refresh menu
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/DuplicateEntryPanel.java
@@ -44,8 +44,8 @@
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.Entry;
import org.opends.admin.ads.util.ConnectionWrapper;
import org.opends.guitools.controlpanel.browser.BrowserController;
import org.opends.guitools.controlpanel.browser.ConnectionWithControls;
import org.opends.guitools.controlpanel.ui.nodes.BasicNode;
import org.opends.guitools.controlpanel.util.BackgroundTask;
import org.opends.guitools.controlpanel.util.LDAPEntryReader;
@@ -307,7 +307,7 @@
      errors.add(ERR_CTRL_PANEL_DUPLICATE_ENTRY_PARENT_DN_NOT_VALID.get());
      setPrimaryInvalid(lParentDN);
    }
    else if (!entryExists(parentDN))
    else if (!entryExists(DN.valueOf(parentDN)))
    {
      errors.add(ERR_CTRL_PANEL_DUPLICATE_ENTRY_PARENT_DOES_NOT_EXIST.get());
      setPrimaryInvalid(lParentDN);
@@ -447,7 +447,7 @@
      @Override
      public Entry processBackgroundTask() throws Throwable
      {
        ConnectionWrapper conn = controller.findConnectionForDisplayedEntry(node);
        ConnectionWithControls conn = controller.findConnectionForDisplayedEntry(node);
        LDAPEntryReader reader = new LDAPEntryReader(node.getDN(), conn);
        sleepIfRequired(700, t1);
        return reader.processBackgroundTask();
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/NewGroupPanel.java
@@ -190,8 +190,7 @@
        {
          try
          {
            DN.valueOf(member);
            if (!entryExists(member))
            if (!entryExists(DN.valueOf(member)))
            {
              errorFound = true;
              errors.add(ERR_CTRL_PANEL_MEMBER_NOT_FOUND.get(member));
@@ -258,13 +257,13 @@
      String ref = referenceGroup.getText().trim();
      try
      {
        DN.valueOf(ref);
        if (!entryExists(ref))
        DN refDN = DN.valueOf(ref);
        if (!entryExists(refDN))
        {
          errorFound = true;
          errors.add(ERR_CTRL_PANEL_REFERENCE_GROUP_NOT_FOUND.get());
        }
        else if (!hasObjectClass(ref, ServerConstants.OC_GROUP_OF_URLS))
        else if (!hasObjectClass(refDN, ServerConstants.OC_GROUP_OF_URLS))
        {
          errorFound = true;
          errors.add(ERR_CTRL_PANEL_REFERENCE_GROUP_NOT_DYNAMIC.get());
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java
@@ -71,6 +71,7 @@
import org.forgerock.i18n.LocalizableMessageBuilder;
import org.forgerock.i18n.LocalizableMessageDescriptor;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.LdapException;
import org.forgerock.opendj.ldap.requests.SearchRequest;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
@@ -1999,15 +2000,13 @@
  }
  /**
   * Tells whether an entry exists or not. Actually it tells if we could find a
   * given entry or not.
   * Tells whether an entry exists or not. Actually it tells if we could find a given entry or not.
   *
   * @param dn
   *          the DN of the entry to look for.
   * @return <CODE>true</CODE> if the entry with the provided DN could be found
   *         and <CODE>false</CODE> otherwise.
   * @return {@code true} if the entry with the provided DN could be found, {@code false} otherwise.
   */
  protected boolean entryExists(final String dn)
  protected boolean entryExists(final DN dn)
  {
    try
    {
@@ -2021,17 +2020,16 @@
  }
  /**
   * Tells whether a given entry exists and contains one of the specified object
   * classes.
   * Tells whether a given entry exists and contains one of the specified object classes.
   *
   * @param dn
   *          the DN of the entry.
   * @param objectClasses
   *          the object classes to check.
   * @return <CODE>true</CODE> if the entry exists and contains one of the
   *         specified object classes and <CODE>false</CODE> otherwise.
   * @return {@code true} if the entry exists and contains one of the specified object classes,
   *         {@code false} otherwise.
   */
  protected boolean hasObjectClass(final String dn, final String... objectClasses)
  protected boolean hasObjectClass(final DN dn, final String... objectClasses)
  {
    SearchRequest request = newSearchRequest(dn, BASE_OBJECT, ALL_OBJECTS_FILTER, OBJECTCLASS_ATTRIBUTE_TYPE_NAME);
    try (ConnectionEntryReader entryReader = getInfo().getConnection().getConnection().search(request))
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/util/LDAPEntryReader.java
@@ -28,7 +28,7 @@
import org.forgerock.opendj.ldap.requests.Requests;
import org.forgerock.opendj.ldap.requests.SearchRequest;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.opends.admin.ads.util.ConnectionWrapper;
import org.opends.guitools.controlpanel.browser.ConnectionWithControls;
import org.opends.guitools.controlpanel.event.EntryReadErrorEvent;
import org.opends.guitools.controlpanel.event.EntryReadEvent;
import org.opends.guitools.controlpanel.event.EntryReadListener;
@@ -41,7 +41,7 @@
public class LDAPEntryReader extends BackgroundTask<Entry>
{
  private final DN dn;
  private final ConnectionWrapper conn;
  private final ConnectionWithControls conn;
  private final Set<EntryReadListener> listeners = new HashSet<>();
  private boolean isOver;
  private boolean notifyListeners;
@@ -51,7 +51,7 @@
   * @param dn the DN of the entry.
   * @param conn the connection to the server.
   */
  public LDAPEntryReader(DN dn, ConnectionWrapper conn)
  public LDAPEntryReader(DN dn, ConnectionWithControls conn)
  {
    this.dn = dn;
    this.conn = conn;
@@ -64,7 +64,7 @@
    isOver = false;
    final Filter filter = Filter.valueOf("(|(objectclass=*)(objectclass=ldapsubentry))");
    SearchRequest request = Requests.newSearchRequest(dn, BASE_OBJECT, filter, "*", "+");
    SearchResultEntry sr = conn.getConnection().searchSingleEntry(request);
    SearchResultEntry sr = conn.searchSingleEntry(request);
    if (isInterrupted())
    {
      isOver = true;