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

Jean-Noël Rouvignac
04.21.2016 867e35d3947bd5f2e6c0baaf502312ca618a00ea
Partial OPENDJ-2625 Convert all code that uses JNDI to use the SDK instead

ModifyEntryTask.java:
In modifyAndRename(), use the newRDN in the call to Connection.modifyDN(),
because this is what the JNDI code was doing: SearchResult.getName()
returns the RDN (while SearchResultEntry.getName() returns the DN)

fixup
1 files deleted
9 files modified
700 ■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/admin/ads/SubtreeDeleteControl.java 38 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ConnectionUtils.java 64 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/BrowserController.java 18 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/NodeRefresher.java 39 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/AddToGroupTask.java 131 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/ModifyEntryTask.java 134 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/ResetUserPasswordTask.java 93 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/Task.java 110 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/LDIFViewEntryPanel.java 32 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/util/Utilities.java 41 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/admin/ads/SubtreeDeleteControl.java
File was deleted
opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ConnectionUtils.java
@@ -19,7 +19,6 @@
import java.io.IOException;
import java.net.ConnectException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;
@@ -27,8 +26,6 @@
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
@@ -487,67 +484,6 @@
  }
  /**
   * Returns the String representation of the first value of an attribute in a
   * LDAP entry.
   * @param entry the entry.
   * @param attrName the attribute name.
   * @return the String representation of the first value of an attribute in a
   * LDAP entry.
   * @throws NamingException if there is an error processing the entry.
   */
  public static String getFirstValue(SearchResult entry, String attrName)
  throws NamingException
  {
    String v = null;
    Attributes attrs = entry.getAttributes();
    if (attrs != null)
    {
      Attribute attr = attrs.get(attrName);
      if (attr != null && attr.size() > 0)
      {
        Object o = attr.get();
        if (o instanceof String)
        {
          v = (String)o;
        }
        else
        {
          v = String.valueOf(o);
        }
      }
    }
    return v;
  }
  /**
   * Returns a Set with the String representation of the values of an attribute
   * in a LDAP entry.  The returned Set will never be null.
   * @param entry the entry.
   * @param attrName the attribute name.
   * @return a Set with the String representation of the values of an attribute
   * in a LDAP entry.
   * @throws NamingException if there is an error processing the entry.
   */
  public static Set<String> getValues(SearchResult entry, String attrName)
  throws NamingException
  {
    Set<String> values = new HashSet<>();
    Attributes attrs = entry.getAttributes();
    if (attrs != null)
    {
      Attribute attr = attrs.get(attrName);
      if (attr != null)
      {
        for (int i=0; i<attr.size(); i++)
        {
          values.add((String)attr.get(i));
        }
      }
    }
    return values;
  }
  /**
   * Returns the first attribute value in this attribute decoded as a UTF-8 string.
   *
   * @param sr
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/BrowserController.java
@@ -62,7 +62,6 @@
import org.opends.guitools.controlpanel.ui.nodes.SuffixNode;
import org.opends.guitools.controlpanel.ui.renderer.BrowserCellRenderer;
import org.opends.guitools.controlpanel.util.NumSubordinateHacker;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.server.config.ConfigConstants;
import org.opends.server.types.HostPort;
import org.opends.server.types.LDAPURL;
@@ -914,15 +913,14 @@
    if (node instanceof SuffixNode)
    {
      DN dn = node.getDN();
      String dnStr = dn.toString();
      return dn.equals(ADSContext.getAdministrationSuffixDN()) ||
          Utilities.areDnsEqual(dnStr, ConfigConstants.DN_DEFAULT_SCHEMA_ROOT) ||
          Utilities.areDnsEqual(dnStr, ConfigConstants.DN_TASK_ROOT) ||
          Utilities.areDnsEqual(dnStr, ConfigConstants.DN_CONFIG_ROOT) ||
          Utilities.areDnsEqual(dnStr, ConfigConstants.DN_MONITOR_ROOT) ||
          Utilities.areDnsEqual(dnStr, ConfigConstants.DN_TRUST_STORE_ROOT) ||
          Utilities.areDnsEqual(dnStr, ConfigConstants.DN_BACKUP_ROOT) ||
          Utilities.areDnsEqual(dnStr, DN_EXTERNAL_CHANGELOG_ROOT);
      return dn.equals(ADSContext.getAdministrationSuffixDN())
          || dn.equals(DN.valueOf(ConfigConstants.DN_DEFAULT_SCHEMA_ROOT))
          || dn.equals(DN.valueOf(ConfigConstants.DN_TASK_ROOT))
          || dn.equals(DN.valueOf(ConfigConstants.DN_CONFIG_ROOT))
          || dn.equals(DN.valueOf(ConfigConstants.DN_MONITOR_ROOT))
          || dn.equals(DN.valueOf(ConfigConstants.DN_TRUST_STORE_ROOT))
          || dn.equals(DN.valueOf(ConfigConstants.DN_BACKUP_ROOT))
          || dn.equals(DN.valueOf(DN_EXTERNAL_CHANGELOG_ROOT));
    }
    else
    {
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/NodeRefresher.java
@@ -30,12 +30,7 @@
import javax.naming.InterruptedNamingException;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.SizeLimitExceededException;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.LdapName;
import javax.swing.SwingUtilities;
import javax.swing.tree.TreeNode;
@@ -345,42 +340,36 @@
   * Performs the search in the case the user specified a custom filter.
   * @param dn the parent DN we perform the search from.
   * @param conn the connection to be used.
   * @throws NamingException if a problem occurred.
   * @throws IOException if a problem occurred.
   */
  private void searchForCustomFilter(String dn, ConnectionWrapper conn)
  throws NamingException
  private void searchForCustomFilter(String dn, ConnectionWrapper conn) throws IOException
  {
    SearchControls ctls = controller.getBasicSearchControls();
    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    ctls.setReturningAttributes(new String[]{});
    ctls.setCountLimit(1);
    NamingEnumeration<SearchResult> s = conn.getLdapContext().search(new LdapName(dn),
              controller.getFilter(),
              ctls);
    try
    SearchRequest request = newSearchRequest(dn, WHOLE_SUBTREE, controller.getFilter())
        .setSizeLimit(1);
    try (ConnectionEntryReader entryReader = conn.getConnection().search(request))
    {
      if (!s.hasMore())
      if (!entryReader.hasNext())
      {
        throw new NameNotFoundException("Entry "+dn+
        throw LdapException.newLdapException(ResultCode.NO_SUCH_OBJECT, "Entry " + dn +
            " does not verify filter "+controller.getFilter());
      }
      while (s.hasMore())
      while (entryReader.hasNext())
      {
        s.next();
        entryReader.readEntry();
      }
    }
    catch (SizeLimitExceededException slme)
    catch (LdapException e)
    {
      if (!e.getResult().getResultCode().equals(ResultCode.SIZE_LIMIT_EXCEEDED))
      {
        throw e;
      }
      // We are just searching for an entry, but if there is more than one
      // this exception will be thrown.  We call sr.hasMore after the
      // first entry has been retrieved to avoid sending a systematic
      // abandon when closing the s NamingEnumeration.
      // See CR 6976906.
    }
    finally
    {
      s.close();
    }
  }
  /** Read the local entry associated to the current node. */
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/AddToGroupTask.java
@@ -14,30 +14,35 @@
 * Copyright 2008-2010 Sun Microsystems, Inc.
 * Portions Copyright 2013-2016 ForgeRock AS.
 */
package org.opends.guitools.controlpanel.task;
import static org.forgerock.opendj.ldap.ModificationType.*;
import static org.forgerock.opendj.ldap.SearchScope.*;
import static org.forgerock.opendj.ldap.requests.Requests.*;
import static org.opends.admin.ads.util.ConnectionUtils.*;
import static org.opends.guitools.controlpanel.browser.BrowserController.*;
import static org.opends.messages.AdminToolMessages.*;
import static org.opends.server.util.ServerConstants.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.swing.SwingUtilities;
import org.opends.admin.ads.util.ConnectionUtils;
import org.opends.guitools.controlpanel.browser.BrowserController;
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;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.forgerock.opendj.ldif.ConnectionEntryReader;
import org.opends.guitools.controlpanel.datamodel.BackendDescriptor;
import org.opends.guitools.controlpanel.datamodel.BaseDNDescriptor;
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
@@ -45,9 +50,6 @@
import org.opends.guitools.controlpanel.ui.ProgressDialog;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.messages.AdminToolMessages;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.ldap.DN;
import org.opends.server.util.ServerConstants;
/** The class that is in charge of adding a set of entries to a set of static groups. */
public class AddToGroupTask extends Task
@@ -154,14 +156,11 @@
    {
      for (final DN groupDn : groupDns)
      {
        final Collection<ModificationItem> modifications =
          getModifications(groupDn, dns);
        ModifyRequest request = newModifyRequest(groupDn);
        addModifications(groupDn, dns, request);
        final List<Modification> modifications = request.getModifications();
        if (!modifications.isEmpty())
        {
          ModificationItem[] mods =
          new ModificationItem[modifications.size()];
          modifications.toArray(mods);
          SwingUtilities.invokeLater(new Runnable()
          {
            @Override
@@ -175,8 +174,7 @@
            }
          });
          getInfo().getConnection().getLdapContext().modifyAttributes(
              Utilities.getJNDIName(groupDn.toString()), mods);
          getInfo().getConnection().getConnection().modify(request);
          SwingUtilities.invokeLater(new Runnable()
          {
@@ -203,89 +201,36 @@
   * Returns the modifications that must be made to the provided group.
   * @param groupDn the DN of the static group that must be updated.
   * @param dns the list of entry DNs that must be added to the group.
   * @return the list of modifications (in form of ModificationItem) that
   *  must be made to the provided group.
   * @throws NamingException if an error occurs.
   * @param modRequest
   * @throws IOException if an error occurs.
   */
  private Collection<ModificationItem> getModifications(DN groupDn,
  Set<DN> dns) throws NamingException
  private void addModifications(DN groupDn, Set<DN> dns, ModifyRequest modRequest) throws IOException
  {
    ArrayList<ModificationItem> modifications = new ArrayList<>();
    // Search for the group entry
    SearchControls ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
    ctls.setReturningAttributes(
        new String[] {
            ServerConstants.OBJECTCLASS_ATTRIBUTE_TYPE_NAME,
            ServerConstants.ATTR_MEMBER,
            ServerConstants.ATTR_UNIQUE_MEMBER
        });
    String filter = BrowserController.ALL_OBJECTS_FILTER;
    NamingEnumeration<SearchResult> result =
      getInfo().getConnection().getLdapContext().search(
          Utilities.getJNDIName(groupDn.toString()),
          filter, ctls);
    SearchRequest searchRequest = newSearchRequest(groupDn, BASE_OBJECT, Filter.valueOf(ALL_OBJECTS_FILTER),
        OBJECTCLASS_ATTRIBUTE_TYPE_NAME,
        ATTR_MEMBER,
        ATTR_UNIQUE_MEMBER);
    try
    try (ConnectionEntryReader reader = getInfo().getConnection().getConnection().search(searchRequest))
    {
      String memberAttr = ServerConstants.ATTR_MEMBER;
      while (result.hasMore())
      String memberAttr = ATTR_MEMBER;
      while (reader.hasNext())
      {
        SearchResult sr = result.next();
        Set<String> objectClasses =
          ConnectionUtils.getValues(sr, ServerConstants
            .OBJECTCLASS_ATTRIBUTE_TYPE_NAME);
        if (objectClasses.contains(ServerConstants.OC_GROUP_OF_UNIQUE_NAMES))
        SearchResultEntry sr = reader.readEntry();
        Set<String> objectClasses = asSetOfString(sr, OBJECTCLASS_ATTRIBUTE_TYPE_NAME);
        if (objectClasses.contains(OC_GROUP_OF_UNIQUE_NAMES))
        {
          memberAttr = ServerConstants.ATTR_UNIQUE_MEMBER;
          memberAttr = ATTR_UNIQUE_MEMBER;
        }
        Set<String> values = ConnectionUtils.getValues(sr, memberAttr);
        Set<String> dnsToAdd = new LinkedHashSet<>();
        if (values != null)
        {
          for (DN newDn : dns)
          {
            boolean found = false;
            for (String dn : values)
            {
              if (Utilities.areDnsEqual(dn, newDn.toString()))
              {
                found = true;
                break;
              }
            }
            if (!found)
            {
              dnsToAdd.add(newDn.toString());
            }
          }
        }
        else
        {
          for (DN newDn : dns)
          {
            dnsToAdd.add(newDn.toString());
          }
        }
        Set<DN> dnsToAdd = new LinkedHashSet<>(dns);
        // remove all existing members
        dnsToAdd.removeAll(asSetOfDN(sr, memberAttr));
        if (!dnsToAdd.isEmpty())
        {
          Attribute attribute = new BasicAttribute(memberAttr);
          for (String dn : dnsToAdd)
          {
            attribute.add(dn);
          }
          modifications.add(new ModificationItem(
              DirContext.ADD_ATTRIBUTE,
              attribute));
          modRequest.addModification(ADD, memberAttr, dnsToAdd.toArray());
        }
      }
    }
    finally
    {
      result.close();
    }
    return modifications;
  }
}
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/ModifyEntryTask.java
@@ -16,6 +16,8 @@
 */
package org.opends.guitools.controlpanel.task;
import static org.forgerock.opendj.ldap.ModificationType.*;
import static org.forgerock.opendj.ldap.requests.Requests.*;
import static org.opends.messages.AdminToolMessages.*;
import static org.opends.server.config.ConfigConstants.*;
@@ -26,11 +28,6 @@
import java.util.Set;
import java.util.TreeSet;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.swing.SwingUtilities;
import javax.swing.tree.TreePath;
@@ -39,7 +36,12 @@
import org.forgerock.opendj.ldap.AttributeDescription;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.LdapException;
import org.forgerock.opendj.ldap.LinkedAttribute;
import org.forgerock.opendj.ldap.Modification;
import org.forgerock.opendj.ldap.ModificationType;
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;
@@ -65,8 +67,8 @@
  private boolean hasModifications;
  private org.forgerock.opendj.ldap.Entry oldEntry;
  private DN oldDn;
  private ArrayList<ModificationItem> modifications;
  private ModificationItem passwordModification;
  private List<Modification> modifications;
  private Modification passwordModification;
  private Entry newEntry;
  private BrowserController controller;
  private TreePath treePath;
@@ -109,9 +111,9 @@
    modifications = getModifications(newEntry, oldEntry, getInfo());
    // Find password modifications
    for (ModificationItem mod : modifications)
    for (Modification mod : modifications)
    {
      if ("userPassword".equalsIgnoreCase(mod.getAttribute().getID()))
      if ("userPassword".equalsIgnoreCase(mod.getAttribute().getAttributeDescriptionAsString()))
      {
        passwordModification = mod;
        break;
@@ -208,10 +210,6 @@
      if (!mustRename)
      {
        if (!modifications.isEmpty()) {
          ModificationItem[] mods =
          new ModificationItem[modifications.size()];
          modifications.toArray(mods);
          SwingUtilities.invokeLater(new Runnable()
          {
            @Override
@@ -226,7 +224,7 @@
            }
          });
          conn.getLdapContext().modifyAttributes(Utilities.getJNDIName(oldEntry.getName().toString()), mods);
          conn.getConnection().modify(newModifyRequest0(oldEntry.getName(), modifications));
          SwingUtilities.invokeLater(new Runnable()
          {
@@ -264,25 +262,7 @@
        && state == State.FINISHED_SUCCESSFULLY
        && passwordModification != null)
    {
      try
      {
        Object o = passwordModification.getAttribute().get();
        String sPwd;
        if (o instanceof byte[])
        {
          try
          {
            sPwd = new String((byte[])o, "UTF-8");
          }
          catch (Throwable t)
          {
            throw new RuntimeException("Unexpected error: "+t, t);
          }
        }
        else
        {
          sPwd = String.valueOf(o);
        }
      String sPwd = passwordModification.getAttribute().firstValueAsString();
        ResetUserPasswordTask newTask = new ResetUserPasswordTask(getInfo(),
            getProgressDialog(), (BasicNode)treePath.getLastPathComponent(),
            controller, sPwd.toCharArray());
@@ -302,12 +282,6 @@
            getInfo());
        getProgressDialog().setVisible(true);
      }
      catch (NamingException ne)
      {
        // This should not happen
        throw new RuntimeException("Unexpected exception: "+ne, ne);
      }
    }
  }
  /**
@@ -319,12 +293,12 @@
   * @param originalMods the original modifications (these are required since
   * we might want to update them).
   * @throws CannotRenameException if we cannot perform the modification.
   * @throws NamingException if an error performing the modification occurs.
   * @throws LdapException if an error performing the modification occurs.
   */
  private void modifyAndRename(ConnectionWrapper conn, final DN oldDN,
      org.forgerock.opendj.ldap.Entry originalEntry,
      final Entry newEntry, final ArrayList<ModificationItem> originalMods)
      throws CannotRenameException, NamingException
      final Entry newEntry, final List<Modification> originalMods)
      throws CannotRenameException, LdapException
  {
    RDN oldRDN = oldDN.rdn();
    RDN newRDN = newEntry.getName().rdn();
@@ -351,8 +325,7 @@
      }
    });
    conn.getLdapContext().rename(Utilities.getJNDIName(oldDn.toString()),
        Utilities.getJNDIName(newEntry.getName().toString()));
    conn.getConnection().modifyDN(newModifyDNRequest(oldDn, newRDN));
    final TreePath[] newPath = {null};
@@ -372,9 +345,7 @@
      }
    });
    ModificationItem[] mods = new ModificationItem[originalMods.size()];
    originalMods.toArray(mods);
    if (mods.length > 0)
    if (originalMods.size() > 0)
    {
      SwingUtilities.invokeLater(new Runnable()
      {
@@ -390,7 +361,7 @@
        }
      });
      conn.getLdapContext().modifyAttributes(Utilities.getJNDIName(newEntry.getName().toString()), mods);
      conn.getConnection().modify(newModifyRequest0(newEntry.getName(), originalMods));
      SwingUtilities.invokeLater(new Runnable()
      {
@@ -408,6 +379,16 @@
    }
  }
  private ModifyRequest newModifyRequest0(DN dn, final Collection<Modification> mods)
  {
    ModifyRequest modRequest = newModifyRequest(dn);
    for (Modification mod : mods)
    {
      modRequest.addModification(mod);
    }
    return modRequest;
  }
  private boolean rdnTypeChanged(RDN oldRDN, RDN newRDN)
  {
    if (newRDN.size() != oldRDN.size())
@@ -437,11 +418,11 @@
    return false;
  }
  private boolean userChangedObjectclass(final ArrayList<ModificationItem> mods)
  private boolean userChangedObjectclass(final List<Modification> mods)
  {
    for (ModificationItem mod : mods)
    for (Modification mod : mods)
    {
      if (ATTR_OBJECTCLASS.equalsIgnoreCase(mod.getAttribute().getID()))
      if (ATTR_OBJECTCLASS.equalsIgnoreCase(mod.getAttribute().getAttributeDescriptionAsString()))
      {
        return true;
      }
@@ -469,9 +450,9 @@
   * @param info the ControlPanelInfo, used to retrieve the schema for instance.
   * @return the modifications to apply between two entries.
   */
  public static ArrayList<ModificationItem> getModifications(Entry newEntry,
  public static List<Modification> getModifications(Entry newEntry,
      org.forgerock.opendj.ldap.Entry oldEntry, ControlPanelInfo info) {
    ArrayList<ModificationItem> modifications = new ArrayList<>();
    List<Modification> modifications = new ArrayList<>();
    Schema schema = info.getServerDescriptor().getSchema();
    List<org.opends.server.types.Attribute> newAttrs = newEntry.getAttributes();
@@ -479,7 +460,6 @@
    for (org.opends.server.types.Attribute attr : newAttrs)
    {
      AttributeDescription attrDesc = attr.getAttributeDescription();
      final String attrName = attrDesc.toString();
      if (!ViewEntryPanel.isEditable(attrDesc, schema))
      {
        continue;
@@ -541,9 +521,7 @@
        }
        if (!vs.isEmpty())
        {
          modifications.add(new ModificationItem(
              DirContext.ADD_ATTRIBUTE,
              createAttribute(attrName, newValues)));
          modifications.add(newModification(ADD, attrDesc, newValues));
        }
      } else {
        final List<ByteString> oldValues = toList(oldAttr);
@@ -560,17 +538,13 @@
        if (toDelete.size() + toAdd.size() >= newValues.size() &&
            !isAttributeInNewRdn)
        {
          modifications.add(new ModificationItem(
              DirContext.REPLACE_ATTRIBUTE,
              createAttribute(attrName, newValues)));
          modifications.add(newModification(REPLACE, attrDesc, newValues));
        }
        else
        {
          if (!toDelete.isEmpty())
          {
            modifications.add(new ModificationItem(
                DirContext.REMOVE_ATTRIBUTE,
                createAttribute(attrName, toDelete)));
            modifications.add(newModification(DELETE, attrDesc, toDelete));
          }
          if (!toAdd.isEmpty())
          {
@@ -581,9 +555,7 @@
            }
            if (!vs.isEmpty())
            {
              modifications.add(new ModificationItem(
                  DirContext.ADD_ATTRIBUTE,
                  createAttribute(attrName, vs)));
              modifications.add(newModification(ADD, attrDesc, vs));
            }
          }
        }
@@ -602,14 +574,23 @@
      if (!newEntry.hasAttribute(AttributeDescription.valueOf(attrDesc.getNameOrOID())) && !oldAttr.isEmpty())
      {
        modifications.add(new ModificationItem(
            DirContext.REMOVE_ATTRIBUTE,
            new BasicAttribute(attrDesc.toString())));
        modifications.add(newModification(DELETE, attrDesc));
      }
    }
    return modifications;
  }
  private static Modification newModification(ModificationType modType, AttributeDescription attrDesc)
  {
    return new Modification(modType, new LinkedAttribute(attrDesc));
  }
  private static Modification newModification(
      ModificationType modType, AttributeDescription attrDesc, Collection<?> values)
  {
    return new Modification(modType, new LinkedAttribute(attrDesc, values));
  }
  private static List<ByteString> toList(org.forgerock.opendj.ldap.Attribute oldAttr)
  {
    List<ByteString> results = new ArrayList<>();
@@ -620,21 +601,6 @@
    return results;
  }
  /**
   * Creates a JNDI attribute using an attribute name and a set of values.
   * @param attrName the attribute name.
   * @param values the values.
   * @return a JNDI attribute using an attribute name and a set of values.
   */
  private static Attribute createAttribute(String attrName, List<ByteString> values) {
    Attribute attribute = new BasicAttribute(attrName);
    for (ByteString value : values)
    {
      attribute.add(value.toByteArray());
    }
    return attribute;
  }
  private static List<ByteString> disjunction(List<ByteString> values2, List<ByteString> values1)
  {
    List<ByteString> results = new ArrayList<>();
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/ResetUserPasswordTask.java
@@ -14,25 +14,28 @@
 * Copyright 2008-2010 Sun Microsystems, Inc.
 * Portions Copyright 2014-2016 ForgeRock AS.
 */
package org.opends.guitools.controlpanel.task;
import static org.forgerock.opendj.ldap.SearchScope.*;
import static org.forgerock.opendj.ldap.requests.Requests.*;
import static org.opends.admin.ads.util.ConnectionUtils.*;
import static org.opends.messages.AdminToolMessages.*;
import static org.opends.server.config.ConfigConstants.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.ldap.DN;
import org.opends.admin.ads.util.ConnectionUtils;
import org.forgerock.opendj.ldap.Filter;
import org.forgerock.opendj.ldap.LdapException;
import org.forgerock.opendj.ldap.requests.SearchRequest;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.forgerock.opendj.ldif.ConnectionEntryReader;
import org.opends.admin.ads.util.ConnectionWrapper;
import org.opends.guitools.controlpanel.browser.BrowserController;
import org.opends.guitools.controlpanel.datamodel.BackendDescriptor;
@@ -40,8 +43,6 @@
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
import org.opends.guitools.controlpanel.ui.ProgressDialog;
import org.opends.guitools.controlpanel.ui.nodes.BasicNode;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.server.config.ConfigConstants;
import org.opends.server.tools.LDAPPasswordModify;
/** The task called when we want to reset the password of the user. */
@@ -128,9 +129,9 @@
  }
  @Override
  protected ArrayList<String> getCommandLineArguments()
  protected List<String> getCommandLineArguments()
  {
    ArrayList<String> args = new ArrayList<>();
    List<String> args = new ArrayList<>();
    if (currentPassword == null)
    {
      args.add("--authzID");
@@ -177,9 +178,8 @@
    lastException = null;
    try
    {
      ArrayList<String> arguments = getCommandLineArguments();
      String[] args = new String[arguments.size()];
      arguments.toArray(args);
      List<String> arguments = getCommandLineArguments();
      String[] args = arguments.toArray(new String[arguments.size()]);
      returnCode = LDAPPasswordModify.mainPasswordModify(args, false,
            outPrintStream, errorPrintStream);
@@ -195,14 +195,10 @@
          // The connections must be updated, just update the environment, which
          // is what we use to clone connections and to launch scripts.
          // The environment will also be used if we want to reconnect.
          getInfo().getConnection().getLdapContext().addToEnvironment(
              Context.SECURITY_CREDENTIALS,
              String.valueOf(newPassword));
          rebind(getInfo().getConnection());
          if (getInfo().getUserDataDirContext() != null)
          {
            getInfo().getUserDataDirContext().getLdapContext().addToEnvironment(
                Context.SECURITY_CREDENTIALS,
                String.valueOf(newPassword));
            rebind(getInfo().getUserDataDirContext());
          }
        }
        state = State.FINISHED_SUCCESSFULLY;
@@ -215,60 +211,35 @@
    }
  }
  private void rebind(ConnectionWrapper conn) throws LdapException
  {
    conn.getConnection().bind(newSimpleBindRequest(conn.getBindDn().toString(), newPassword));
  }
  /**
   * Returns <CODE>true</CODE> if we are bound using the provided entry.  In
   * Returns whether we are bound using the provided entry.  In
   * the case of root entries this is not necessarily the same as using that
   * particular DN (we might be binding using a value specified in
   * ds-cfg-alternate-bind-dn).
   * @param dn the DN.
   * @param conn the connection that we are using to modify the password.
   * @return <CODE>true</CODE> if we are bound using the provided entry.
   * @return {@code true} if we are bound using the provided entry.
   */
  private boolean isBoundAs(DN dn, ConnectionWrapper conn)
  {
    boolean isBoundAs = false;
    DN bindDN = DN.rootDN();
    try
    {
      bindDN = conn.getBindDn();
      isBoundAs = dn.equals(bindDN);
    }
    catch (Throwable t)
    {
      // Ignore
    }
    final DN bindDN = conn.getBindDn();
    boolean isBoundAs = dn.equals(bindDN);
    if (!isBoundAs)
    {
      try
      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))
      {
        SearchControls ctls = new SearchControls();
        ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
        String filter =
          "(|(objectClass=*)(objectclass=ldapsubentry))";
        String attrName = ConfigConstants.ATTR_ROOTDN_ALTERNATE_BIND_DN;
        ctls.setReturningAttributes(new String[] {attrName});
        NamingEnumeration<SearchResult> entries =
            conn.getLdapContext().search(Utilities.getJNDIName(dn.toString()), filter, ctls);
        try
        while (entries.hasNext())
        {
          while (entries.hasMore())
          {
            SearchResult sr = entries.next();
            Set<String> dns = ConnectionUtils.getValues(sr, attrName);
            for (String sDn : dns)
            {
              if (bindDN.equals(DN.valueOf(sDn)))
              {
                isBoundAs = true;
                break;
              }
            }
          }
        }
        finally
        {
          entries.close();
          SearchResultEntry sr = entries.readEntry();
          return asSetOfDN(sr, attrName).contains(bindDN);
        }
      }
      catch (Throwable t)
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/Task.java
@@ -30,14 +30,12 @@
import java.util.Objects;
import java.util.Set;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.ldap.Attribute;
import org.forgerock.opendj.ldap.AttributeDescription;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.Modification;
import org.opends.admin.ads.util.ConnectionWrapper;
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
@@ -57,7 +55,6 @@
import org.opends.server.types.HostPort;
import org.opends.server.types.InitializationException;
import org.opends.server.types.Schema;
import org.opends.server.util.Base64;
import org.opends.server.util.SetupUtils;
import com.forgerock.opendj.cli.CommandBuilder;
@@ -407,49 +404,29 @@
   * to display the command-line equivalent when we do a modification in an
   * entry.  But since some attributes must be obfuscated (like the user
   * password) we pass through this method.
   * @param attrName the attribute name.
   * @param o the attribute value.
   * @param attrDesc the attribute description.
   * @param value the attribute value.
   * @return the obfuscated String representing the attribute value to be
   * displayed in the logs of the user.
   */
  private String obfuscateAttributeStringValue(String attrName, Object o)
  private String obfuscateAttributeStringValue(AttributeDescription attrDesc, ByteString value)
  {
    if (Utilities.mustObfuscate(attrName,
    if (Utilities.mustObfuscate(attrDesc.toString(),
        getInfo().getServerDescriptor().getSchema()))
    {
      return OBFUSCATED_VALUE;
    }
    else if (o instanceof byte[])
    else if (displayBase64(attrDesc.toString()))
    {
      byte[] bytes = (byte[])o;
      if (displayBase64(attrName))
      {
        if (bytes.length > MAX_BINARY_LENGTH_TO_DISPLAY)
      if (value.length() > MAX_BINARY_LENGTH_TO_DISPLAY)
        {
          return INFO_CTRL_PANEL_VALUE_IN_BASE64.get().toString();
        }
        else
        {
          return Base64.encode(bytes);
        }
      return value.toBase64String();
      }
      else
      {
        if (bytes.length > MAX_BINARY_LENGTH_TO_DISPLAY)
        {
          return INFO_CTRL_PANEL_BINARY_VALUE.get().toString();
        }
        else
        {
          // Get the String value
          ByteString v = ByteString.wrap(bytes);
          return v.toString();
        }
      }
    }
    else
    {
      return String.valueOf(o);
      return value.toString();
    }
  }
@@ -801,20 +778,7 @@
   * @param mods the modifications.
   * @param useAdminCtx use the administration connector.
   */
  protected void printEquivalentCommandToModify(DN dn,
      Collection<ModificationItem> mods, boolean useAdminCtx)
  {
    printEquivalentCommandToModify(dn.toString(), mods, useAdminCtx);
  }
  /**
   * Prints the equivalent modify command line in the progress dialog.
   * @param dn the dn of the modified entry.
   * @param mods the modifications.
   * @param useAdminCtx use the administration connector.
   */
  private void printEquivalentCommandToModify(String dn,
      Collection<ModificationItem> mods, boolean useAdminCtx)
  protected void printEquivalentCommandToModify(DN dn, Collection<Modification> mods, boolean useAdminCtx)
  {
    ArrayList<String> args = new ArrayList<>(getObfuscatedCommandLineArguments(
        getConnectionCommandLineArguments(useAdminCtx, true)));
@@ -827,7 +791,7 @@
    sb.append("<br>");
    sb.append("dn: ").append(dn);
    boolean firstChangeType = true;
    for (ModificationItem mod : mods)
    for (Modification mod : mods)
    {
      if (firstChangeType)
      {
@@ -838,45 +802,37 @@
        sb.append("-<br>");
      }
      firstChangeType = false;
      Attribute attr = mod.getAttribute();
      String attrName = attr.getID();
      if (mod.getModificationOp() == DirContext.ADD_ATTRIBUTE)
      AttributeDescription attrDesc = attr.getAttributeDescription();
      switch (mod.getModificationType().asEnum())
      {
        sb.append("add: ").append(attrName).append("<br>");
      case ADD:
        sb.append("add: ").append(attrDesc).append("<br>");
        break;
      case REPLACE:
        sb.append("replace: ").append(attrDesc).append("<br>");
        break;
      case DELETE:
        sb.append("delete: ").append(attrDesc).append("<br>");
        break;
      }
      else if (mod.getModificationOp() == DirContext.REPLACE_ATTRIBUTE)
      for (ByteString value : attr)
      {
        sb.append("replace: ").append(attrName).append("<br>");
      }
      else
      {
        sb.append("delete: ").append(attrName).append("<br>");
      }
      for (int i=0; i<attr.size(); i++)
      {
        try
        {
          Object o = attr.get(i);
          // We are systematically adding the values in binary mode.
          // Use the attribute names to figure out the value to be displayed.
          if (displayBase64(attr.getID()))
        if (displayBase64(attrDesc.toString()))
          {
            sb.append(attrName).append(":: ");
          sb.append(attrDesc).append(":: ");
          }
          else
          {
            sb.append(attrName).append(": ");
          sb.append(attrDesc).append(": ");
          }
          sb.append(obfuscateAttributeStringValue(attrName, o));
        sb.append(obfuscateAttributeStringValue(attrDesc, value));
          sb.append("<br>");
        }
        catch (NamingException ne)
        {
          // Bug
          throw new RuntimeException(
              "Unexpected error parsing modifications: "+ne, ne);
        }
      }
    }
    sb.append("</b><br><br>");
@@ -930,8 +886,8 @@
   * Tells whether the provided attribute's values must be displayed using
   * base 64 when displaying the equivalent command-line or not.
   * @param attrName the attribute name.
   * @return <CODE>true</CODE> if the attribute must be displayed using base 64
   * and <CODE>false</CODE> otherwise.
   * @return {@code true} if the attribute must be displayed using base 64,
   * {@code false} otherwise.
   */
  private boolean displayBase64(String attrName)
  {
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/LDIFViewEntryPanel.java
@@ -41,9 +41,7 @@
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.server.types.LDIFImportConfig;
import org.opends.server.types.OpenDsException;
import org.opends.server.util.Base64;
import org.opends.server.util.LDIFReader;
import org.opends.server.util.StaticUtils;
/** The panel displaying an LDIF view of an entry. */
public class LDIFViewEntryPanel extends ViewEntryPanel
@@ -290,35 +288,17 @@
  /**
   * Returns the equivalent LDIF line for a given attribute and value.
   * @param attrName the attribute name.
   * @param o the value.
   * @param value the value.
   * @return the equivalent LDIF line for the provided attribute and value.
   */
  private String getLDIFLine(String attrName, Object o)
  private String getLDIFLine(String attrName, ByteString value)
  {
    String attrValue;
    if (o instanceof String)
    String v = value.toString();
    if (isBinary(attrName) || Utilities.hasControlCharaters(v))
    {
      if (Utilities.hasControlCharaters((String)o))
      {
        attrValue = Base64.encode(StaticUtils.getBytes((String)o));
        attrName = attrName+":";
      }
      else
      {
        attrValue = (String)o;
      }
    }
    else if (o instanceof byte[])
    {
      attrValue = Base64.encode((byte[])o);
      // To indicate that is base64 encoded
      attrName = attrName+":";
      return attrName + ":: " + value.toBase64String();
    }
    else
    {
      attrValue = String.valueOf(o);
    }
    return attrName+": "+ attrValue;
    return attrName + ": " + v;
  }
}
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/util/Utilities.java
@@ -54,11 +54,7 @@
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.naming.CompositeName;
import javax.naming.InvalidNameException;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.ldap.LdapName;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
@@ -1447,26 +1443,6 @@
  }
  /**
   * Returns whether the provided strings represent the same DN.
   *
   * @param dn1 the first dn to compare.
   * @param dn2 the second dn to compare.
   * @return {@code true} if the provided strings represent the same DN, {@code false} otherwise.
   */
  public static boolean areDnsEqual(String dn1, String dn2)
  {
    try
    {
      LdapName name1 = new LdapName(dn1);
      LdapName name2 = new LdapName(dn2);
      return name1.equals(name2);
    } catch (Exception ex)
    {
      return false;
    }
  }
  /**
   * Returns the attribute name with no options (or subtypes).
   * <p>
   * Note: normal code should use <code>AttributeDescription.valueOf(attrName).getNameOrOID()</code>
@@ -1538,23 +1514,6 @@
  }
  /**
   * Commodity method to get the Name object representing a dn.
   * It is preferable to use Name objects when doing JNDI operations to avoid
   * problems with the '/' character.
   * @param dn the DN as a String.
   * @return a Name object representing the DN.
   * @throws InvalidNameException if the provided DN value is not valid.
   */
  public static Name getJNDIName(String dn) throws InvalidNameException
  {
    Name name = new CompositeName();
    if (dn != null && dn.length() > 0) {
      name.add(dn);
    }
    return name;
  }
  /**
   * Returns the HTML representation of the 'Done' string.
   * @param progressFont the font to be used.
   * @return the HTML representation of the 'Done' string.