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
995 ■■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/BrowserController.java 306 ●●●●● 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 74 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/NodeRefresher.java 135 ●●●●● 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 41 ●●●●● 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 77 ●●●●● 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 38 ●●●● 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,43 +820,42 @@
   * 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) {
        /* 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
         that has children (node), BUT the referral entry in the local server
         has no children.  It won't be included in the filter and it won't
         appear in the tree.  But what we are displaying is the remote entry,
         the result is that we have a NODE that does not appear in the tree and
         so the user cannot browse it.
         This has some side effects:
         If we cannot follow the referral, a leaf will appear on the tree (as it
         if were a node).
         If the referral points to a leaf entry, a leaf will appear on the tree
         (as if it were a node).
         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+")";
      }
      for (String containerClass : containerClasses)
      {
        result += "(objectClass=" + containerClass + ")";
      }
      result += ")";
    }
    else {
      result = filter;
  Filter getChildSearchFilter()
  {
    if (!showContainerOnly)
    {
      return filter;
    }
    return result;
    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
       that has children (node), BUT the referral entry in the local server
       has no children.  It won't be included in the filter and it won't
       appear in the tree.  But what we are displaying is the remote entry,
       the result is that we have a NODE that does not appear in the tree and
       so the user cannot browse it.
       This has some side effects:
       If we cannot follow the referral, a leaf will appear on the tree (as it
       if were a node).
       If the referral points to a leaf entry, a leaf will appear on the tree
       (as if it were a node).
       This is minor compared to the impossibility of browsing a subtree with
       the NODE/LEAF layout.
       */
      result += "(objectClass=referral)";
    }
    for (String containerClass : containerClasses)
    {
      result += "(objectClass=" + containerClass + ")";
    }
    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,28 +71,33 @@
  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)
      {
        return true;
        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)
        .setSizeLimit(1);
    try (ConnectionEntryReader s = conn.getConnection().search(request))
        newSearchRequest(node.getDN(), WHOLE_SUBTREE, controller.getFilter(), NO_ATTRIBUTES)
            .setSizeLimit(1);
    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,20 +604,19 @@
   */
  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),
              useCustomFilter() ? WHOLE_SUBTREE : BASE_OBJECT,
              controller.getChildSearchFilter(),
              NO_ATTRIBUTES)
          controller.findBaseDNForChildEntries(parentNode),
          useCustomFilter() ? WHOLE_SUBTREE : BASE_OBJECT,
          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())
              .setSizeLimit(controller.getMaxChildren());
      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());
            .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)
        HostPort hp = new HostPort(url.getHost(), url.getPort());
        boolean checkSucceeded =
            hp.equals(controller.getConfigurationConnection().getConnectionWrapper().getHostPort())
            && hp.equals(controller.getUserDataConnection().getConnectionWrapper().getHostPort());
        if (!checkSucceeded)
        {
          checkSucceeded = urlHostPort.equals(controller.getUserDataConnection().getHostPort());
          Exception cause = new ReferralLimitExceededException(ERR_CTRL_PANEL_REFERRAL_LOOP.get(url.getRawBaseDN()));
          throw new SearchAbandonException(State.FAILED, cause, referral);
        }
      }
    }
    catch (OpenDsException odse)
    catch (OpenDsException ignore)
    {
      // Ignore
    }
    if (!checkSucceeded)
    {
      throw new SearchAbandonException(
          State.FAILED, new ReferralLimitExceededException(
              ERR_CTRL_PANEL_REFERRAL_LOOP.get(url.getRawBaseDN())), referral);
    }
  }
}
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;
        printProgressCreatingEntry();
        conn.getConnection().add(Converters.from(newEntry));
      }
      SwingUtilities.invokeLater(new Runnable()
      {
        @Override
        public void run()
        {
          printEquivalentCommand();
          getProgressDialog().appendProgressHtml(
              Utilities.getProgressWithPoints(
                  INFO_CTRL_PANEL_CREATING_ENTRY.get(dn),
                  ColorAndFontConstants.progressFont));
        }
      });
      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,23 +1199,15 @@
              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;
                }
                ControlPanelInfo info = getInfo();
                controller.setConnections(
                    info.getServerDescriptor(), info.getConnection(), info.getUserDataDirContext());
                applyButtonClicked();
              }
            };
            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,23 +1244,13 @@
      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();
          }
          entryPane.getController().setSorted(sortUserData.isSelected());
        }
      });
      followReferrals.addActionListener(new ActionListener()
@@ -1270,17 +1258,7 @@
        @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;