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

neil_a_wilson
15.40.2006 6b7027bb28c10ddf23e00def117d352b736ffe4d
opends/src/server/org/opends/server/tools/LDAPCompare.java
@@ -30,6 +30,8 @@
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Reader;
import java.text.ParseException;
import java.util.ArrayList;
@@ -48,6 +50,7 @@
import org.opends.server.protocols.ldap.LDAPMessage;
import org.opends.server.protocols.ldap.ProtocolOp;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.NullOutputStream;
import org.opends.server.util.Base64;
import org.opends.server.util.PasswordReader;
import org.opends.server.util.args.ArgumentException;
@@ -80,16 +83,27 @@
  // The message ID counter to use for requests.
  private AtomicInteger nextMessageID;
  // The print stream to use for standard error.
  private PrintStream err;
  // The print stream to use for standard output.
  private PrintStream out;
  /**
   * Constructor for the LDAPCompare object.
   *
   * @param  nextMessageID  The message ID counter to use for requests.
   * @param  out            The print stream to use for standard output.
   * @param  err            The print stream to use for standard error.
   */
  public LDAPCompare(AtomicInteger nextMessageID)
  public LDAPCompare(AtomicInteger nextMessageID, PrintStream out,
                     PrintStream err)
  {
    this.nextMessageID = nextMessageID;
    this.out           = out;
    this.err           = err;
  }
  /**
@@ -178,8 +192,7 @@
                                     attributeType, attrValOctetStr);
    int msgID = MSGID_PROCESSING_COMPARE_OPERATION;
    System.out.println(getMessage(msgID, attributeType, attrValOctetStr,
                                  dnOctetStr));
    out.println(getMessage(msgID, attributeType, attrValOctetStr, dnOctetStr));
    if(!compareOptions.showOperations())
    {
@@ -203,7 +216,7 @@
        {
          msgID = MSGID_OPERATION_FAILED;
          String msg = getMessage(msgID, "COMPARE", line, ae.getMessage());
          System.err.println(msg);
          err.println(msg);
          return;
        }
      }
@@ -224,16 +237,16 @@
        if(resultCode == COMPARE_FALSE)
        {
          msgID = MSGID_COMPARE_OPERATION_RESULT_FALSE;
          System.out.println(getMessage(msgID, line));
          out.println(getMessage(msgID, line));
        } else if(resultCode == COMPARE_TRUE)
        {
          msgID = MSGID_COMPARE_OPERATION_RESULT_TRUE;
          System.out.println(getMessage(msgID, line));
          out.println(getMessage(msgID, line));
        } else
        {
          msgID = MSGID_OPERATION_FAILED;
          String msg = getMessage(msgID, "COMPARE", line, errorMessage);
          System.err.println(msg);
          err.println(msg);
        }
      }
    }
@@ -247,7 +260,7 @@
  public static void main(String[] args)
  {
    int retCode = mainCompare(args);
    int retCode = mainCompare(args, true, System.out, System.err);
    if(retCode != 0)
    {
@@ -266,6 +279,50 @@
  public static int mainCompare(String[] args)
  {
    return mainCompare(args, true, System.out, System.err);
  }
  /**
   * Parses the provided command-line arguments and uses that information to
   * run the ldapcompare tool.
   *
   * @param  args              The command-line arguments provided to this
   *                           program.
   * @param  initializeServer  Indicates whether to initialize the server.
   * @param  outStream         The output stream to use for standard output, or
   *                           <CODE>null</CODE> if standard output is not
   *                           needed.
   * @param  errStream         The output stream to use for standard error, or
   *                           <CODE>null</CODE> if standard error is not
   *                           needed.
   *
   * @return The error code.
   */
  public static int mainCompare(String[] args, boolean initializeServer,
                                OutputStream outStream, OutputStream errStream)
  {
    PrintStream out;
    if (outStream == null)
    {
      out = NullOutputStream.printStream();
    }
    else
    {
      out = new PrintStream(outStream);
    }
    PrintStream err;
    if (errStream == null)
    {
      err = NullOutputStream.printStream();
    }
    else
    {
      err = new PrintStream(errStream);
    }
    LDAPConnectionOptions connectionOptions = new LDAPConnectionOptions();
    LDAPCompareOptions compareOptions = new LDAPCompareOptions();
    LDAPConnection connection = null;
@@ -363,7 +420,7 @@
      showUsage = new BooleanArgument("showUsage", 'H', "help",
                                    MSGID_DESCRIPTION_SHOWUSAGE);
      argParser.addArgument(showUsage);
      argParser.setUsageArgument(showUsage);
      argParser.setUsageArgument(showUsage, out);
      controlStr = new StringArgument("controls", 'J', "controls", false,
                false, true,
                "{controloid[:criticality[:value|::b64value|:<fileurl]]}",
@@ -406,7 +463,7 @@
      int    msgID   = MSGID_ENCPW_CANNOT_INITIALIZE_ARGS;
      String message = getMessage(msgID, ae.getMessage());
      System.err.println(message);
      err.println(message);
      return 1;
    }
@@ -420,8 +477,8 @@
      int    msgID   = MSGID_ENCPW_ERROR_PARSING_ARGS;
      String message = getMessage(msgID, ae.getMessage());
      System.err.println(message);
      System.err.println(argParser.getUsage());
      err.println(message);
      err.println(argParser.getUsage());
      return 1;
    }
@@ -433,8 +490,8 @@
    if(bindPassword.isPresent() && bindPasswordFile.isPresent())
    {
      System.err.println("ERROR: Both -w and -j flags specified. " +
                          "Please specify one.");
      err.println("ERROR: Both -w and -j flags specified. " +
                  "Please specify one.");
      return 1;
    }
@@ -442,7 +499,7 @@
    if(attrAndDNStrings.isEmpty())
    {
      System.err.println("No Attributes specified for comparison");
      err.println("No Attributes specified for comparison");
      return 1;
    }
@@ -459,8 +516,8 @@
    int idx = attributeString.indexOf(":");
    if(idx == -1)
    {
      System.err.println("Invalid attribute string:" + attributeString);
      System.err.println("Attribute string must be in one of the " +
      err.println("Invalid attribute string:" + attributeString);
      err.println("Attribute string must be in one of the " +
      "following forms: attribute:value, attribute::base64value, " +
      "attribute:<fileURL" );
      return 1;
@@ -505,7 +562,7 @@
    } catch (ArgumentException ae)
    {
      assert debugException(CLASS_NAME, "main", ae);
      System.err.println(ae.getMessage());
      err.println(ae.getMessage());
      return 1;
    }
@@ -515,14 +572,14 @@
      if(versionNumber != 2 && versionNumber != 3)
      {
        int msgID = MSGID_DESCRIPTION_INVALID_VERSION;
        System.err.println(getMessage(msgID, versionNumber));
        err.println(getMessage(msgID, versionNumber));
        return 1;
      }
      connectionOptions.setVersionNumber(versionNumber);
    } catch(ArgumentException ae)
    {
      assert debugException(CLASS_NAME, "main", ae);
      System.err.println(ae.getMessage());
      err.println(ae.getMessage());
      return 1;
    }
@@ -535,14 +592,13 @@
      // read the password from the stdin.
      try
      {
        System.out.print(getMessage(MSGID_LDAPAUTH_PASSWORD_PROMPT,
                                    bindDNValue));
        out.print(getMessage(MSGID_LDAPAUTH_PASSWORD_PROMPT, bindDNValue));
        char[] pwChars = PasswordReader.readPassword();
        bindPasswordValue = new String(pwChars);
      } catch(Exception ex)
      {
        assert debugException(CLASS_NAME, "main", ex);
        System.err.println(ex.getMessage());
        err.println(ex.getMessage());
        return 1;
      }
    } else if(bindPasswordValue == null)
@@ -566,8 +622,8 @@
      LDAPControl ctrl = LDAPToolUtils.getControl(ctrlString);
      if(ctrl == null)
      {
        System.err.println("Invalid control specified:" + ctrlString);
        System.out.println(argParser.getUsage());
        err.println("Invalid control specified:" + ctrlString);
        err.println(argParser.getUsage());
        return 1;
      }
      compareOptions.getControls().add(ctrl);
@@ -588,8 +644,8 @@
      }
      catch (LDAPException le)
      {
        System.err.println(getMessage(MSGID_LDAP_ASSERTION_INVALID_FILTER,
                                      le.getMessage()));
        err.println(getMessage(MSGID_LDAP_ASSERTION_INVALID_FILTER,
                               le.getMessage()));
        return 1;
      }
    }
@@ -626,23 +682,25 @@
    {
      if(!connectionOptions.useSSL() && !connectionOptions.useStartTLS())
      {
        System.err.println("SASL External requires either SSL or StartTLS " +
                           "options to be requested.");
        err.println("SASL External requires either SSL or StartTLS " +
                    "options to be requested.");
        return 1;
      }
      if(keyStorePathValue == null)
      {
        System.err.println("SASL External requires a path to the SSL " +
                           "client certificate keystore.");
        err.println("SASL External requires a path to the SSL " +
                    "client certificate keystore.");
        return 1;
      }
    }
    try
    {
      // Bootstrap and initialize directory data structures.
      DirectoryServer.bootstrapClient();
      if (initializeServer)
      {
        // Bootstrap and initialize directory data structures.
        DirectoryServer.bootstrapClient();
      }
      // Connect to the specified host with the supplied userDN and password.
      SSLConnectionFactory sslConnectionFactory = null;
@@ -657,11 +715,11 @@
      AtomicInteger nextMessageID = new AtomicInteger(1);
      connection = new LDAPConnection(hostNameValue, portNumber,
                                      connectionOptions);
                                      connectionOptions, out, err);
      connection.connectToHost(bindDNValue, bindPasswordValue, nextMessageID);
      LDAPCompare ldapCompare = new LDAPCompare(nextMessageID);
      LDAPCompare ldapCompare = new LDAPCompare(nextMessageID, out, err);
      if(fileNameValue == null && dnStrings.isEmpty())
      {
        // Read from stdin.
@@ -682,19 +740,19 @@
    } catch(LDAPException le)
    {
      assert debugException(CLASS_NAME, "main", le);
      System.err.println(le.getMessage());
      err.println(le.getMessage());
      int code = le.getResultCode();
      return code;
    } catch(LDAPConnectionException lce)
    {
        assert debugException(CLASS_NAME, "main", lce);
        System.err.println(lce.getMessage());
        err.println(lce.getMessage());
        int code = lce.getErrorCode();
        return code;
    } catch(Exception e)
    {
      assert debugException(CLASS_NAME, "main", e);
      System.err.println(e.getMessage());
      err.println(e.getMessage());
      return 1;
    } finally
    {
opends/src/server/org/opends/server/tools/LDAPConnection.java
@@ -26,6 +26,7 @@
 */
package org.opends.server.tools;
import java.io.PrintStream;
import java.net.ConnectException;
import java.net.Socket;
import java.net.UnknownHostException;
@@ -79,6 +80,9 @@
  private ASN1Reader asn1Reader;
  private int versionNumber = 3;
  private PrintStream out;
  private PrintStream err;
  /**
   * Constructor for the LDAPConnection object.
   *
@@ -89,10 +93,28 @@
   */
  public LDAPConnection(String host, int port, LDAPConnectionOptions options)
  {
    this(host, port, options, System.out, System.err);
  }
  /**
   * Constructor for the LDAPConnection object.
   *
   * @param   host    The hostname to send the request to.
   * @param   port    The port number on which the directory server is accepting
   *                  requests.
   * @param  options  The set of options for this connection.
   * @param  out      The print stream to use for standard output.
   * @param  err      The print stream to use for standard error.
   */
  public LDAPConnection(String host, int port, LDAPConnectionOptions options,
                        PrintStream out, PrintStream err)
  {
    this.hostName = host;
    this.portNumber = port;
    this.connectionOptions = options;
    this.versionNumber = options.getVersionNumber();
    this.out = out;
    this.err = err;
  }
  /**
@@ -263,7 +285,7 @@
      }
      if(result != null)
      {
        System.out.println(result);
        out.println(result);
      }
      for (LDAPControl c : responseControls)
@@ -275,14 +297,14 @@
          {
            int    msgID   = MSGID_BIND_AUTHZID_RETURNED;
            String message = getMessage(msgID, controlValue.stringValue());
            System.out.println(message);
            out.println(message);
          }
        }
        else if (c.getOID().equals(OID_NS_PASSWORD_EXPIRED))
        {
          int    msgID   = MSGID_BIND_PASSWORD_EXPIRED;
          String message = getMessage(msgID);
          System.out.println(message);
          out.println(message);
        }
        else if (c.getOID().equals(OID_NS_PASSWORD_EXPIRING))
        {
@@ -295,7 +317,7 @@
          int    msgID   = MSGID_BIND_PASSWORD_EXPIRING;
          String message = getMessage(msgID, timeString);
          System.out.println(message);
          out.println(message);
        }
        else if (c.getOID().equals(OID_PASSWORD_POLICY_CONTROL))
        {
@@ -311,17 +333,17 @@
              case PASSWORD_EXPIRED:
                int    msgID   = MSGID_BIND_PASSWORD_EXPIRED;
                String message = getMessage(msgID);
                System.out.println(message);
                out.println(message);
                break;
              case ACCOUNT_LOCKED:
                msgID   = MSGID_BIND_ACCOUNT_LOCKED;
                message = getMessage(msgID);
                System.out.println(message);
                out.println(message);
                break;
              case CHANGE_AFTER_RESET:
                msgID   = MSGID_BIND_MUST_CHANGE_PASSWORD;
                message = getMessage(msgID);
                System.out.println(message);
                out.println(message);
                break;
            }
          }
@@ -338,12 +360,12 @@
                int    msgID   = MSGID_BIND_PASSWORD_EXPIRING;
                String message = getMessage(msgID, timeString);
                System.out.println(message);
                out.println(message);
                break;
              case GRACE_LOGINS_REMAINING:
                msgID   = MSGID_BIND_GRACE_LOGINS_REMAINING;
                message = getMessage(msgID, pwPolicyControl.getWarningValue());
                System.out.println(message);
                out.println(message);
                break;
            }
          }
opends/src/server/org/opends/server/tools/LDAPDelete.java
@@ -30,6 +30,8 @@
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.LinkedList;
@@ -46,6 +48,7 @@
import org.opends.server.protocols.ldap.LDAPException;
import org.opends.server.protocols.ldap.LDAPMessage;
import org.opends.server.protocols.ldap.ProtocolOp;
import org.opends.server.types.NullOutputStream;
import org.opends.server.util.PasswordReader;
import org.opends.server.util.args.ArgumentException;
import org.opends.server.util.args.ArgumentParser;
@@ -77,16 +80,27 @@
  // The message ID counter to use for requests.
  private AtomicInteger nextMessageID;
  // The print stream to use for standard error.
  private PrintStream err;
  // The print stream to use for standard output.
  private PrintStream out;
  /**
   * Constructor for the LDAPDelete object.
   *
   * @param  nextMessageID  The next message ID to use for requests.
   * @param  out            The print stream to use for standard output.
   * @param  err            The print stream to use for standard error.
   */
  public LDAPDelete(AtomicInteger nextMessageID)
  public LDAPDelete(AtomicInteger nextMessageID, PrintStream out,
                    PrintStream err)
  {
    this.nextMessageID = nextMessageID;
    this.out           = out;
    this.err           = err;
  }
  /**
@@ -162,7 +176,7 @@
    protocolOp = new DeleteRequestProtocolOp(asn1OctetStr);
    int msgID = MSGID_PROCESSING_OPERATION;
    System.out.println(getMessage(msgID, "DELETE", asn1OctetStr));
    out.println(getMessage(msgID, "DELETE", asn1OctetStr));
    if(!deleteOptions.showOperations())
    {
      LDAPMessage message = new LDAPMessage(nextMessageID.getAndIncrement(),
@@ -185,7 +199,7 @@
        {
          msgID = MSGID_OPERATION_FAILED;
          String msg = getMessage(msgID, "DELETE", line, ae.getMessage());
          System.err.println(msg);
          err.println(msg);
          return;
        }
      }
@@ -206,12 +220,12 @@
        {
          msgID = MSGID_OPERATION_FAILED;
          String msg = getMessage(msgID, "DELETE", line, errorMessage);
          System.err.println(msg);
          err.println(msg);
        } else
        {
          msgID = MSGID_OPERATION_SUCCESSFUL;
          String msg = getMessage(msgID, "DELETE", line);
          System.out.println(msg);
          out.println(msg);
        }
      }
    }
@@ -225,7 +239,7 @@
  public static void main(String[] args)
  {
    int retCode = mainDelete(args);
    int retCode = mainDelete(args, true, System.out, System.err);
    if(retCode != 0)
    {
@@ -244,6 +258,50 @@
  public static int mainDelete(String[] args)
  {
    return mainDelete(args, true, System.out, System.err);
  }
  /**
   * Parses the provided command-line arguments and uses that information to
   * run the ldapdelete tool.
   *
   * @param  args              The command-line arguments provided to this
   *                           program.
   * @param  initializeServer  Indicates whether to initialize the server.
   * @param  outStream         The output stream to use for standard output, or
   *                           <CODE>null</CODE> if standard output is not
   *                           needed.
   * @param  errStream         The output stream to use for standard error, or
   *                           <CODE>null</CODE> if standard error is not
   *                           needed.
   *
   * @return The error code.
   */
  public static int mainDelete(String[] args, boolean initializeServer,
                               OutputStream outStream, OutputStream errStream)
  {
    PrintStream out;
    if (outStream == null)
    {
      out = NullOutputStream.printStream();
    }
    else
    {
      out = new PrintStream(outStream);
    }
    PrintStream err;
    if (errStream == null)
    {
      err = NullOutputStream.printStream();
    }
    else
    {
      err = new PrintStream(errStream);
    }
    LDAPConnectionOptions connectionOptions = new LDAPConnectionOptions();
    LDAPDeleteOptions deleteOptions = new LDAPDeleteOptions();
    LDAPConnection connection = null;
@@ -335,7 +393,7 @@
      showUsage = new BooleanArgument("showUsage", 'H', "help",
                                      MSGID_DESCRIPTION_SHOWUSAGE);
      argParser.addArgument(showUsage);
      argParser.setUsageArgument(showUsage);
      argParser.setUsageArgument(showUsage, out);
      controlStr = new StringArgument("controls", 'J', "controls", false, false,
           true, "{controloid[:criticality[:value|::b64value|:<fileurl]]}",
           null, null, MSGID_DESCRIPTION_CONTROLS);
@@ -372,7 +430,7 @@
      int    msgID   = MSGID_ENCPW_CANNOT_INITIALIZE_ARGS;
      String message = getMessage(msgID, ae.getMessage());
      System.err.println(message);
      err.println(message);
      return 1;
    }
@@ -386,22 +444,22 @@
      int    msgID   = MSGID_ENCPW_ERROR_PARSING_ARGS;
      String message = getMessage(msgID, ae.getMessage());
      System.err.println(message);
      System.err.println(argParser.getUsage());
      err.println(message);
      err.println(argParser.getUsage());
      return 1;
    }
    // If we should just display usage information, then print it and exit.
    if (showUsage.isPresent())
    {
      System.out.println(argParser.getUsage());
      out.println(argParser.getUsage());
      return 0;
    }
    if(bindPassword.isPresent() && bindPasswordFile.isPresent())
    {
      System.err.println("ERROR: Both -w and -j flags specified. " +
                         "Please specify one.");
      err.println("ERROR: Both -w and -j flags specified. " +
                  "Please specify one.");
      return 1;
    }
@@ -413,7 +471,7 @@
    } catch(ArgumentException ae)
    {
      assert debugException(CLASS_NAME, "main", ae);
      System.err.println(ae.getMessage());
      err.println(ae.getMessage());
      return 1;
    }
@@ -423,14 +481,14 @@
      if(versionNumber != 2 && versionNumber != 3)
      {
        int msgID = MSGID_DESCRIPTION_INVALID_VERSION;
        System.err.println(getMessage(msgID, versionNumber));
        err.println(getMessage(msgID, versionNumber));
        return 1;
      }
      connectionOptions.setVersionNumber(versionNumber);
    } catch(ArgumentException ae)
    {
      assert debugException(CLASS_NAME, "main", ae);
      System.err.println(ae.getMessage());
      err.println(ae.getMessage());
      return 1;
    }
@@ -442,14 +500,13 @@
      // read the password from the stdin.
      try
      {
        System.out.print(getMessage(MSGID_LDAPAUTH_PASSWORD_PROMPT,
                                    bindDNValue));
        out.print(getMessage(MSGID_LDAPAUTH_PASSWORD_PROMPT, bindDNValue));
        char[] pwChars = PasswordReader.readPassword();
        bindPasswordValue = new String(pwChars);
      } catch(Exception ex)
      {
        assert debugException(CLASS_NAME, "main", ex);
        System.err.println(ex.getMessage());
        err.println(ex.getMessage());
        return 1;
      }
    } else if(bindPasswordValue == null)
@@ -474,8 +531,8 @@
      LDAPControl ctrl = LDAPToolUtils.getControl(ctrlString);
      if(ctrl == null)
      {
        System.err.println("Invalid control specified:" + ctrlString);
        System.out.println(argParser.getUsage());
        err.println("Invalid control specified:" + ctrlString);
        err.println(argParser.getUsage());
        return 1;
      }
      deleteOptions.getControls().add(ctrl);
@@ -524,23 +581,25 @@
    {
      if(!connectionOptions.useSSL() && !connectionOptions.useStartTLS())
      {
        System.err.println("SASL External requires either SSL or StartTLS " +
                           "options to be requested.");
        err.println("SASL External requires either SSL or StartTLS " +
                    "options to be requested.");
        return 1;
      }
      if(keyStorePathValue == null)
      {
        System.err.println("SASL External requires a path to the SSL " +
                           "client certificate keystore.");
        err.println("SASL External requires a path to the SSL " +
                    "client certificate keystore.");
        return 1;
      }
    }
    try
    {
      // Bootstrap and initialize directory data structures.
      DirectoryServer.bootstrapClient();
      if (initializeServer)
      {
        // Bootstrap and initialize directory data structures.
        DirectoryServer.bootstrapClient();
      }
      // Connect to the specified host with the supplied userDN and password.
      SSLConnectionFactory sslConnectionFactory = null;
@@ -555,10 +614,10 @@
      AtomicInteger nextMessageID = new AtomicInteger(1);
      connection = new LDAPConnection(hostNameValue, portNumber,
                                      connectionOptions);
                                      connectionOptions, out, err);
      connection.connectToHost(bindDNValue, bindPasswordValue, nextMessageID);
      LDAPDelete ldapDelete = new LDAPDelete(nextMessageID);
      LDAPDelete ldapDelete = new LDAPDelete(nextMessageID, out, err);
      if(fileNameValue == null && dnStrings.isEmpty())
      {
        // Read from stdin.
@@ -578,19 +637,19 @@
    } catch(LDAPException le)
    {
      assert debugException(CLASS_NAME, "main", le);
      System.err.println(le.getMessage());
      err.println(le.getMessage());
      int code = le.getResultCode();
      return code;
    } catch(LDAPConnectionException lce)
    {
      assert debugException(CLASS_NAME, "main", lce);
      System.err.println(lce.getMessage());
      err.println(lce.getMessage());
      int code = lce.getErrorCode();
      return code;
    } catch(Exception e)
    {
      assert debugException(CLASS_NAME, "main", e);
      System.err.println(e.getMessage());
      err.println(e.getMessage());
      return 1;
    } finally
    {
opends/src/server/org/opends/server/tools/LDAPModify.java
@@ -29,6 +29,8 @@
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@@ -58,6 +60,7 @@
import org.opends.server.protocols.ldap.ProtocolOp;
import org.opends.server.types.Attribute;
import org.opends.server.types.LDIFImportConfig;
import org.opends.server.types.NullOutputStream;
import org.opends.server.util.AddChangeRecordEntry;
import org.opends.server.util.ChangeRecordEntry;
import org.opends.server.util.LDIFException;
@@ -94,6 +97,12 @@
  // The message ID counter to use for requests.
  private AtomicInteger nextMessageID;
  // The print stream to use for standard error.
  private PrintStream err;
  // The print stream to use for standard output.
  private PrintStream out;
  // The LDIF file name.
  private String fileName = null;
@@ -103,8 +112,11 @@
   * @param  fileName       The name of the file containing the LDIF data to use
   *                        for the modifications.
   * @param  nextMessageID  The message ID counter to use for requests.
   * @param  out            The print stream to use for standard output.
   * @param  err            The print stream to use for standard error.
   */
  public LDAPModify(String fileName, AtomicInteger nextMessageID)
  public LDAPModify(String fileName, AtomicInteger nextMessageID,
                    PrintStream out, PrintStream err)
  {
    if(fileName == null)
    {
@@ -115,6 +127,8 @@
    }
    this.nextMessageID = nextMessageID;
    this.out           = out;
    this.err           = err;
  }
@@ -181,7 +195,7 @@
          int    msgID   = MSGID_LDIF_FILE_INVALID_LDIF_ENTRY;
          String message = getMessage(msgID, le.getLineNumber(), fileName,
                                      String.valueOf(le));
          System.err.println(message);
          err.println(message);
          continue;
        }
      } catch (Exception e)
@@ -206,7 +220,7 @@
        {
          int    msgID   = MSGID_LDIF_FILE_READ_ERROR;
          String message = getMessage(msgID, fileName, String.valueOf(e));
          System.err.println(message);
          err.println(message);
          continue;
        }
      }
@@ -246,13 +260,13 @@
          }
          protocolOp = new AddRequestProtocolOp(asn1OctetStr, attributes);
          msgID = MSGID_PROCESSING_OPERATION;
          System.out.println(getMessage(msgID, operationType, asn1OctetStr));
          out.println(getMessage(msgID, operationType, asn1OctetStr));
          break;
        case DELETE:
          operationType = "DELETE";
          protocolOp = new DeleteRequestProtocolOp(asn1OctetStr);
          msgID = MSGID_PROCESSING_OPERATION;
          System.out.println(getMessage(msgID, operationType, asn1OctetStr));
          out.println(getMessage(msgID, operationType, asn1OctetStr));
          break;
        case MODIFY:
          operationType = "MODIFY";
@@ -261,7 +275,7 @@
            new ArrayList<LDAPModification>(modEntry.getModifications());
          protocolOp = new ModifyRequestProtocolOp(asn1OctetStr, mods);
          msgID = MSGID_PROCESSING_OPERATION;
          System.out.println(getMessage(msgID, operationType, asn1OctetStr));
          out.println(getMessage(msgID, operationType, asn1OctetStr));
          break;
        case MODIFY_DN:
          operationType = "MODIFY DN";
@@ -281,7 +295,7 @@
                 modDNEntry.deleteOldRDN());
          }
          msgID = MSGID_PROCESSING_OPERATION;
          System.out.println(getMessage(msgID, operationType, asn1OctetStr));
          out.println(getMessage(msgID, operationType, asn1OctetStr));
          break;
        default:
          break;
@@ -304,8 +318,8 @@
        {
          assert debugException(CLASS_NAME, "readAndExecute", ae);
          msgID = MSGID_OPERATION_FAILED;
          System.err.println(getMessage(msgID, operationType, asn1OctetStr,
                                        ae.getMessage()));
          err.println(getMessage(msgID, operationType, asn1OctetStr,
                                 ae.getMessage()));
          if(!modifyOptions.continueOnError())
          {
            throw new IOException(ae.getMessage());
@@ -365,22 +379,22 @@
            throw new LDAPException(resultCode, msgID, msg);
          } else
          {
            System.err.println(msg);
            err.println(msg);
          }
        } else
        {
          msgID = MSGID_OPERATION_SUCCESSFUL;
          String msg = getMessage(msgID, operationType, asn1OctetStr);
          System.out.println(msg);
          out.println(msg);
          if (errorMessage != null)
          {
            System.out.println(errorMessage);
            out.println(errorMessage);
          }
          if (referralURLs != null)
          {
            System.out.println(referralURLs);
            out.println(referralURLs);
          }
        }
@@ -394,7 +408,7 @@
            if (controlValue == null)
            {
              msgID = MSGID_LDAPMODIFY_PREREAD_NO_VALUE;
              System.err.println(getMessage(msgID));
              err.println(getMessage(msgID));
              continue;
            }
@@ -409,20 +423,20 @@
            catch (ASN1Exception ae)
            {
              msgID = MSGID_LDAPMODIFY_PREREAD_CANNOT_DECODE_VALUE;
              System.err.println(getMessage(msgID, ae.getMessage()));
              err.println(getMessage(msgID, ae.getMessage()));
              continue;
            }
            catch (LDAPException le)
            {
              msgID = MSGID_LDAPMODIFY_PREREAD_CANNOT_DECODE_VALUE;
              System.err.println(getMessage(msgID, le.getMessage()));
              err.println(getMessage(msgID, le.getMessage()));
              continue;
            }
            StringBuilder buffer = new StringBuilder();
            searchEntry.toLDIF(buffer, 78);
            System.out.println(getMessage(MSGID_LDAPMODIFY_PREREAD_ENTRY));
            System.out.println(buffer);
            out.println(getMessage(MSGID_LDAPMODIFY_PREREAD_ENTRY));
            out.println(buffer);
          }
          else if (oid.equals(OID_LDAP_READENTRY_POSTREAD))
          {
@@ -430,7 +444,7 @@
            if (controlValue == null)
            {
              msgID = MSGID_LDAPMODIFY_POSTREAD_NO_VALUE;
              System.err.println(getMessage(msgID));
              err.println(getMessage(msgID));
              continue;
            }
@@ -445,20 +459,20 @@
            catch (ASN1Exception ae)
            {
              msgID = MSGID_LDAPMODIFY_POSTREAD_CANNOT_DECODE_VALUE;
              System.err.println(getMessage(msgID, ae.getMessage()));
              err.println(getMessage(msgID, ae.getMessage()));
              continue;
            }
            catch (LDAPException le)
            {
              msgID = MSGID_LDAPMODIFY_POSTREAD_CANNOT_DECODE_VALUE;
              System.err.println(getMessage(msgID, le.getMessage()));
              err.println(getMessage(msgID, le.getMessage()));
              continue;
            }
            StringBuilder buffer = new StringBuilder();
            searchEntry.toLDIF(buffer, 78);
            System.out.println(getMessage(MSGID_LDAPMODIFY_POSTREAD_ENTRY));
            System.out.println(buffer);
            out.println(getMessage(MSGID_LDAPMODIFY_POSTREAD_ENTRY));
            out.println(buffer);
          }
        }
      }
@@ -474,7 +488,7 @@
  public static void main(String[] args)
  {
    int retCode = mainModify(args);
    int retCode = mainModify(args, true, System.out, System.err);
    if(retCode != 0)
    {
@@ -494,6 +508,51 @@
  public static int mainModify(String[] args)
  {
    return mainModify(args, true, System.out, System.err);
  }
  /**
   * Parses the provided command-line arguments and uses that information to
   * run the ldapmodify tool.
   *
   * @param  args              The command-line arguments provided to this
   *                           program.
   * @param  initializeServer  Indicates whether to initialize the server.
   * @param  outStream         The output stream to use for standard output, or
   *                           <CODE>null</CODE> if standard output is not
   *                           needed.
   * @param  errStream         The output stream to use for standard error, or
   *                           <CODE>null</CODE> if standard error is not
   *                           needed.
   *
   * @return The error code.
   */
  public static int mainModify(String[] args, boolean initializeServer,
                               OutputStream outStream, OutputStream errStream)
  {
    PrintStream out;
    if (outStream == null)
    {
      out = NullOutputStream.printStream();
    }
    else
    {
      out = new PrintStream(outStream);
    }
    PrintStream err;
    if (errStream == null)
    {
      err = NullOutputStream.printStream();
    }
    else
    {
      err = new PrintStream(errStream);
    }
    LDAPConnectionOptions connectionOptions = new LDAPConnectionOptions();
    LDAPModifyOptions modifyOptions = new LDAPModifyOptions();
    LDAPConnection connection = null;
@@ -597,7 +656,7 @@
      showUsage = new BooleanArgument("showUsage", 'H', "help",
                                    MSGID_DESCRIPTION_SHOWUSAGE);
      argParser.addArgument(showUsage);
      argParser.setUsageArgument(showUsage);
      argParser.setUsageArgument(showUsage, out);
      controlStr = new StringArgument("controls", 'J', "controls", false,
                false, true,
                "{controloid[:criticality[:value|::b64value|:<fileurl]]}",
@@ -654,7 +713,7 @@
      int    msgID   = MSGID_ENCPW_CANNOT_INITIALIZE_ARGS;
      String message = getMessage(msgID, ae.getMessage());
      System.err.println(message);
      err.println(message);
      return 1;
    }
@@ -668,8 +727,8 @@
      int    msgID   = MSGID_ENCPW_ERROR_PARSING_ARGS;
      String message = getMessage(msgID, ae.getMessage());
      System.err.println(message);
      System.err.println(argParser.getUsage());
      err.println(message);
      err.println(argParser.getUsage());
      return 1;
    }
@@ -681,8 +740,8 @@
    if(bindPassword.isPresent() && bindPasswordFile.isPresent())
    {
      System.err.println("ERROR: Both -w and -j flags specified. " +
                         "Please specify one.");
      err.println("ERROR: Both -w and -j flags specified. " +
                  "Please specify one.");
      return 1;
    }
@@ -694,7 +753,7 @@
    } catch(ArgumentException ae)
    {
      assert debugException(CLASS_NAME, "main", ae);
      System.err.println(ae.getMessage());
      err.println(ae.getMessage());
      return 1;
    }
@@ -704,14 +763,14 @@
      if(versionNumber != 2 && versionNumber != 3)
      {
        int msgID = MSGID_DESCRIPTION_INVALID_VERSION;
        System.err.println(getMessage(msgID, versionNumber));
        err.println(getMessage(msgID, versionNumber));
        return 1;
      }
      connectionOptions.setVersionNumber(versionNumber);
    } catch(ArgumentException ae)
    {
      assert debugException(CLASS_NAME, "main", ae);
      System.err.println(ae.getMessage());
      err.println(ae.getMessage());
      return 1;
    }
@@ -723,14 +782,13 @@
      // read the password from the stdin.
      try
      {
        System.out.print(getMessage(MSGID_LDAPAUTH_PASSWORD_PROMPT,
                                    bindDNValue));
        out.print(getMessage(MSGID_LDAPAUTH_PASSWORD_PROMPT, bindDNValue));
        char[] pwChars = PasswordReader.readPassword();
        bindPasswordValue = new String(pwChars);
      } catch(Exception ex)
      {
        assert debugException(CLASS_NAME, "main", ex);
        System.err.println(ex.getMessage());
        err.println(ex.getMessage());
        return 1;
      }
    } else if(bindPasswordValue == null)
@@ -755,8 +813,8 @@
      LDAPControl ctrl = LDAPToolUtils.getControl(ctrlString);
      if(ctrl == null)
      {
        System.err.println("Invalid control specified:" + ctrlString);
        System.out.println(argParser.getUsage());
        err.println("Invalid control specified:" + ctrlString);
        err.println(argParser.getUsage());
        return 1;
      }
      modifyOptions.getControls().add(ctrl);
@@ -787,8 +845,8 @@
      }
      catch (LDAPException le)
      {
        System.err.println(getMessage(MSGID_LDAP_ASSERTION_INVALID_FILTER,
                                      le.getMessage()));
        err.println(getMessage(MSGID_LDAP_ASSERTION_INVALID_FILTER,
                               le.getMessage()));
        return 1;
      }
    }
@@ -862,22 +920,25 @@
    {
      if(!connectionOptions.useSSL() && !connectionOptions.useStartTLS())
      {
        System.err.println("SASL External requires either SSL or StartTLS " +
                           "options to be requested.");
        err.println("SASL External requires either SSL or StartTLS " +
                    "options to be requested.");
        return 1;
      }
      if(keyStorePathValue == null)
      {
        System.err.println("SASL External requires a path to the SSL " +
                           "client certificate keystore.");
        err.println("SASL External requires a path to the SSL " +
                    "client certificate keystore.");
        return 1;
      }
    }
    try
    {
      // Bootstrap and initialize directory data structures.
      DirectoryServer.bootstrapClient();
      if (initializeServer)
      {
        // Bootstrap and initialize directory data structures.
        DirectoryServer.bootstrapClient();
      }
      // Connect to the specified host with the supplied userDN and password.
      SSLConnectionFactory sslConnectionFactory = null;
@@ -892,10 +953,11 @@
      AtomicInteger nextMessageID = new AtomicInteger(1);
      connection = new LDAPConnection(hostNameValue, portNumber,
                                      connectionOptions);
                                      connectionOptions, out, err);
      connection.connectToHost(bindDNValue, bindPasswordValue, nextMessageID);
      LDAPModify ldapModify = new LDAPModify(fileNameValue, nextMessageID);
      LDAPModify ldapModify = new LDAPModify(fileNameValue, nextMessageID,
                                             out, err);
      InputStream is = System.in;
      if(fileNameValue != null)
      {
@@ -905,19 +967,19 @@
    } catch(LDAPException le)
    {
      assert debugException(CLASS_NAME, "main", le);
      System.err.println(le.getMessage());
      err.println(le.getMessage());
      int code = le.getResultCode();
      return code;
    } catch(LDAPConnectionException lce)
    {
      assert debugException(CLASS_NAME, "main", lce);
      System.err.println(lce.getMessage());
      err.println(lce.getMessage());
      int code = lce.getErrorCode();
      return code;
    } catch(Exception e)
    {
      assert debugException(CLASS_NAME, "main", e);
      System.err.println(e.getMessage());
      err.println(e.getMessage());
      return 1;
    } finally
    {
opends/src/server/org/opends/server/tools/LDAPSearch.java
@@ -29,6 +29,8 @@
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
@@ -65,6 +67,7 @@
import org.opends.server.protocols.ldap.SearchResultEntryProtocolOp;
import org.opends.server.protocols.ldap.SearchResultReferenceProtocolOp;
import org.opends.server.types.DN;
import org.opends.server.types.NullOutputStream;
import static org.opends.server.loggers.Debug.*;
import static org.opends.server.messages.MessageHandler.*;
@@ -93,16 +96,27 @@
  // The message ID counter to use for requests.
  private AtomicInteger nextMessageID;
  // The print stream to use for standard error.
  private PrintStream err;
  // The print stream to use for standard output.
  private PrintStream out;
  /**
   * Constructor for the LDAPSearch object.
   *
   * @param  nextMessageID  The message ID counter to use for requests.
   * @param  out            The print stream to use for standard output.
   * @param  err            The print stream to use for standard error.
   */
  public LDAPSearch(AtomicInteger nextMessageID)
  public LDAPSearch(AtomicInteger nextMessageID, PrintStream out,
                    PrintStream err)
  {
    this.nextMessageID = nextMessageID;
    this.out           = out;
    this.err           = err;
  }
@@ -172,13 +186,13 @@
                    EntryChangeNotificationControl ecn =
                         EntryChangeNotificationControl.decodeControl(
                              c.getControl());
                    System.out.println("# Persistent Search Change Type:  " +
                                       ecn.getChangeType().toString());
                    out.println("# Persistent Search Change Type:  " +
                                ecn.getChangeType().toString());
                    DN previousDN = ecn.getPreviousDN();
                    if (previousDN != null)
                    {
                      System.out.println("# Persistent Search Previous DN:  " +
                                         previousDN.toString());
                      out.println("# Persistent Search Previous DN:  " +
                                  previousDN.toString());
                    }
                  } catch (Exception e) {}
                }
@@ -189,49 +203,49 @@
                    AccountUsableResponseControl acrc =
                         AccountUsableResponseControl.decodeControl(
                              c.getControl());
                    System.out.println("# Account Usable Response Control");
                    out.println("# Account Usable Response Control");
                    if (acrc.isUsable())
                    {
                      System.out.println("#   Account is usable");
                      out.println("#   Account is usable");
                      if (acrc.getSecondsBeforeExpiration() > 0)
                      {
                        int    timeToExp    = acrc.getSecondsBeforeExpiration();
                        String timeToExpStr = secondsToTimeString(timeToExp);
                        System.out.println("#   Time until expiration:  " +
                                           timeToExpStr);
                        out.println("#   Time until expiration:  " +
                                    timeToExpStr);
                      }
                    }
                    else
                    {
                      System.out.println("#   Account is not usable");
                      out.println("#   Account is not usable");
                      if (acrc.isInactive())
                      {
                        System.out.println("#   Account is inactive");
                        out.println("#   Account is inactive");
                      }
                      if (acrc.isReset())
                      {
                        System.out.println("#   Password has been reset");
                        out.println("#   Password has been reset");
                      }
                      if (acrc.isExpired())
                      {
                        System.out.println("#   Password is expired");
                        out.println("#   Password is expired");
                        if (acrc.getRemainingGraceLogins() > 0)
                        {
                          System.out.println("#   Grace logins remaining:  " +
                                             acrc.getRemainingGraceLogins());
                          out.println("#   Grace logins remaining:  " +
                                      acrc.getRemainingGraceLogins());
                        }
                      }
                      if (acrc.isLocked())
                      {
                        System.out.println("#   Account is locked");
                        out.println("#   Account is locked");
                        if (acrc.getSecondsBeforeUnlock() > 0)
                        {
                          int timeToUnlock = acrc.getSecondsBeforeUnlock();
                          String timeToUnlockStr =
                                      secondsToTimeString(timeToUnlock);
                          System.out.println("#   Time until automatic " +
                                             "unlock:  " + timeToUnlockStr);
                          out.println("#   Time until automatic unlock:  " +
                                      timeToUnlockStr);
                        }
                      }
                    }
@@ -243,13 +257,13 @@
                   responseMessage.getSearchResultEntryProtocolOp();
              StringBuilder sb = new StringBuilder();
              toLDIF(searchEntryOp, sb, wrapColumn, typesOnly);
              System.out.println(sb.toString());
              out.println(sb.toString());
              break;
            case OP_TYPE_SEARCH_RESULT_REFERENCE:
              SearchResultReferenceProtocolOp searchRefOp =
                   responseMessage.getSearchResultReferenceProtocolOp();
              System.out.println(searchRefOp.toString());
              out.println(searchRefOp.toString());
              break;
            case OP_TYPE_SEARCH_RESULT_DONE:
@@ -262,7 +276,7 @@
              // FIXME - throw exception?
              int msgID = MSGID_SEARCH_OPERATION_INVALID_PROTOCOL;
              String msg = getMessage(msgID, opType);
              System.err.println(msg);
              err.println(msg);
              break;
          }
@@ -277,8 +291,8 @@
          }
          else if (errorMessage != null)
          {
            System.out.println();
            System.out.println(errorMessage);
            out.println();
            out.println(errorMessage);
          }
        } while(opType != OP_TYPE_SEARCH_RESULT_DONE);
@@ -430,7 +444,7 @@
  public static void main(String[] args)
  {
    int retCode = mainSearch(args);
    int retCode = mainSearch(args, true, System.out, System.err);
    if(retCode != 0)
    {
@@ -449,6 +463,49 @@
  public static int mainSearch(String[] args)
  {
    return mainSearch(args, true, System.out, System.err);
  }
  /**
   * Parses the provided command-line arguments and uses that information to
   * run the ldapsearch tool.
   *
   * @param  args              The command-line arguments provided to this
   *                           program.
   * @param  initializeServer  Indicates whether to initialize the server.
   * @param  outStream         The output stream to use for standard output, or
   *                           <CODE>null</CODE> if standard output is not
   *                           needed.
   * @param  errStream         The output stream to use for standard error, or
   *                           <CODE>null</CODE> if standard error is not
   *                           needed.
   *
   * @return The error code.
   */
  public static int mainSearch(String[] args, boolean initializeServer,
                               OutputStream outStream, OutputStream errStream)
  {
    PrintStream out;
    if (outStream == null)
    {
      out = NullOutputStream.printStream();
    }
    else
    {
      out = new PrintStream(outStream);
    }
    PrintStream err;
    if (errStream == null)
    {
      err = NullOutputStream.printStream();
    }
    else
    {
      err = new PrintStream(errStream);
    }
    LDAPConnectionOptions connectionOptions = new LDAPConnectionOptions();
    LDAPSearchOptions searchOptions = new LDAPSearchOptions();
    LDAPConnection connection = null;
@@ -572,7 +629,7 @@
      showUsage = new BooleanArgument("showUsage", 'H', "help",
                                    MSGID_DESCRIPTION_SHOWUSAGE);
      argParser.addArgument(showUsage);
      argParser.setUsageArgument(showUsage);
      argParser.setUsageArgument(showUsage, out);
      controlStr = new StringArgument("controls", 'J', "controls", false,
                false, true,
                "{controloid[:criticality[:value|::b64value|:<fileurl]]}",
@@ -647,7 +704,7 @@
      int    msgID   = MSGID_ENCPW_CANNOT_INITIALIZE_ARGS;
      String message = getMessage(msgID, ae.getMessage());
      System.err.println(message);
      err.println(message);
      return 1;
    }
@@ -661,8 +718,8 @@
      int    msgID   = MSGID_ENCPW_ERROR_PARSING_ARGS;
      String message = getMessage(msgID, ae.getMessage());
      System.err.println(message);
      System.err.println(argParser.getUsage());
      err.println(message);
      err.println(argParser.getUsage());
      return 1;
    }
@@ -683,7 +740,7 @@
      } catch(LDAPException le)
      {
        assert debugException(CLASS_NAME, "main", le);
        System.err.println(le.getMessage());
        err.println(le.getMessage());
        return 1;
      }
      // The rest are attributes
@@ -696,8 +753,8 @@
    if(bindPassword.isPresent() && bindPasswordFile.isPresent())
    {
      System.err.println("ERROR: Both -w and -j flags specified. " +
                          "Please specify one.");
      err.println("ERROR: Both -w and -j flags specified. " +
                  "Please specify one.");
      return 1;
    }
@@ -709,7 +766,7 @@
    } catch(ArgumentException ae)
    {
      assert debugException(CLASS_NAME, "main", ae);
      System.err.println(ae.getMessage());
      err.println(ae.getMessage());
      return 1;
    }
@@ -720,14 +777,14 @@
      if(versionNumber != 2 && versionNumber != 3)
      {
        int msgID = MSGID_DESCRIPTION_INVALID_VERSION;
        System.err.println(getMessage(msgID, versionNumber));
        err.println(getMessage(msgID, versionNumber));
        return 1;
      }
      connectionOptions.setVersionNumber(versionNumber);
    } catch(ArgumentException ae)
    {
      assert debugException(CLASS_NAME, "main", ae);
      System.err.println(ae.getMessage());
      err.println(ae.getMessage());
      return 1;
    }
@@ -748,14 +805,13 @@
      // read the password from the stdin.
      try
      {
        System.out.print(getMessage(MSGID_LDAPAUTH_PASSWORD_PROMPT,
                                    bindDNValue));
        out.print(getMessage(MSGID_LDAPAUTH_PASSWORD_PROMPT, bindDNValue));
        char[] pwChars = PasswordReader.readPassword();
        bindPasswordValue = new String(pwChars);
      } catch(Exception ex)
      {
        assert debugException(CLASS_NAME, "main", ex);
        System.err.println(ex.getMessage());
        err.println(ex.getMessage());
        return 1;
      }
    } else if(bindPasswordValue == null)
@@ -780,7 +836,7 @@
      searchOptions.setSizeLimit(sizeLimit.getIntValue());
    } catch(ArgumentException ex1)
    {
      System.err.println(ex1.getMessage());
      err.println(ex1.getMessage());
      return 1;
    }
    boolean val = searchOptions.setSearchScope(searchScope.getValue());
@@ -800,8 +856,8 @@
      LDAPControl ctrl = LDAPToolUtils.getControl(ctrlString);
      if(ctrl == null)
      {
        System.err.println("Invalid control specified:" + ctrlString);
        System.out.println(argParser.getUsage());
        err.println("Invalid control specified:" + ctrlString);
        err.println(argParser.getUsage());
        return 1;
      }
      searchOptions.getControls().add(ctrl);
@@ -831,7 +887,7 @@
      {
        int    msgID   = MSGID_PSEARCH_MISSING_DESCRIPTOR;
        String message = getMessage(msgID);
        System.err.println(message);
        err.println(message);
        return 1;
      }
      else
@@ -841,7 +897,7 @@
        {
          int    msgID   = MSGID_PSEARCH_DOESNT_START_WITH_PS;
          String message = getMessage(msgID, String.valueOf(infoString));
          System.err.println(message);
          err.println(message);
          return 1;
        }
      }
@@ -880,7 +936,7 @@
          {
            int    msgID   = MSGID_PSEARCH_INVALID_CHANGE_TYPE;
            String message = getMessage(msgID, String.valueOf(token));
            System.err.println(message);
            err.println(message);
            return 1;
          }
        }
@@ -910,7 +966,7 @@
        {
          int    msgID   = MSGID_PSEARCH_INVALID_CHANGESONLY;
          String message = getMessage(msgID, String.valueOf(token));
          System.err.println(message);
          err.println(message);
          return 1;
        }
      }
@@ -931,7 +987,7 @@
        {
          int    msgID   = MSGID_PSEARCH_INVALID_RETURN_ECS;
          String message = getMessage(msgID, String.valueOf(token));
          System.err.println(message);
          err.println(message);
          return 1;
        }
      }
@@ -958,8 +1014,8 @@
      }
      catch (LDAPException le)
      {
        System.err.println(getMessage(MSGID_LDAP_ASSERTION_INVALID_FILTER,
                                      le.getMessage()));
        err.println(getMessage(MSGID_LDAP_ASSERTION_INVALID_FILTER,
                               le.getMessage()));
        return 1;
      }
    }
@@ -978,8 +1034,8 @@
        }
        catch (LDAPException le)
        {
          System.err.println(getMessage(MSGID_LDAP_MATCHEDVALUES_INVALID_FILTER,
                                        le.getMessage()));
          err.println(getMessage(MSGID_LDAP_MATCHEDVALUES_INVALID_FILTER,
                                 le.getMessage()));
          return 1;
        }
      }
@@ -1019,14 +1075,14 @@
    {
      if(!connectionOptions.useSSL() && !connectionOptions.useStartTLS())
      {
        System.err.println("SASL External requires either SSL or StartTLS " +
                           "options to be requested.");
        err.println("SASL External requires either SSL or StartTLS " +
                    "options to be requested.");
        return 1;
      }
      if(keyStorePathValue == null)
      {
        System.err.println("SASL External requires a path to the SSL " +
                           "client certificate keystore.");
        err.println("SASL External requires a path to the SSL " +
                    "client certificate keystore.");
        return 1;
      }
    }
@@ -1053,7 +1109,7 @@
      } catch(Exception e)
      {
        assert debugException(CLASS_NAME, "main", e);
        System.err.println(e.getMessage());
        err.println(e.getMessage());
        return 1;
      }
      finally
@@ -1072,8 +1128,8 @@
    if(filters.isEmpty())
    {
      int msgid = MSGID_SEARCH_NO_FILTERS;
      System.err.println(getMessage(msgid));
      System.err.println(argParser.getUsage());
      err.println(getMessage(msgid));
      err.println(argParser.getUsage());
      return 1;
    }
@@ -1085,8 +1141,11 @@
    try
    {
      // Bootstrap and initialize directory data structures.
      DirectoryServer.bootstrapClient();
      if (initializeServer)
      {
        // Bootstrap and initialize directory data structures.
        DirectoryServer.bootstrapClient();
      }
      // Connect to the specified host with the supplied userDN and password.
      SSLConnectionFactory sslConnectionFactory = null;
@@ -1101,29 +1160,29 @@
      AtomicInteger nextMessageID = new AtomicInteger(1);
      connection = new LDAPConnection(hostNameValue, portNumber,
                                      connectionOptions);
                                      connectionOptions, out, err);
      connection.connectToHost(bindDNValue, bindPasswordValue, nextMessageID);
      LDAPSearch ldapSearch = new LDAPSearch(nextMessageID);
      LDAPSearch ldapSearch = new LDAPSearch(nextMessageID, out, err);
      ldapSearch.executeSearch(connection, baseDNValue, filters, attributes,
                               searchOptions, wrapColumn);
    } catch(LDAPException le)
    {
      assert debugException(CLASS_NAME, "main", le);
      System.err.println(le.getMessage());
      err.println(le.getMessage());
      int code = le.getResultCode();
      return code;
    } catch(LDAPConnectionException lce)
    {
        assert debugException(CLASS_NAME, "main", lce);
        System.err.println(lce.getMessage());
        err.println(lce.getMessage());
        int code = lce.getErrorCode();
        return code;
    } catch(Exception e)
    {
      assert debugException(CLASS_NAME, "main", e);
      System.err.println(e.getMessage());
      err.println(e.getMessage());
      return 1;
    } finally
    {
opends/src/server/org/opends/server/tools/StopDS.java
@@ -29,6 +29,8 @@
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
@@ -54,6 +56,7 @@
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.tasks.ShutdownTask;
import org.opends.server.types.Control;
import org.opends.server.types.NullOutputStream;
import org.opends.server.util.args.ArgumentException;
import org.opends.server.util.args.ArgumentParser;
import org.opends.server.util.args.BooleanArgument;
@@ -90,7 +93,7 @@
   */
  public static void main(String[] args)
  {
    int result = stopDS(args);
    int result = stopDS(args, System.out, System.err);
    if (result != LDAPResultCode.SUCCESS)
    {
@@ -112,6 +115,49 @@
   */
  public static int stopDS(String[] args)
  {
    return stopDS(args, System.out, System.err);
  }
  /**
   * Parses the provided set of command-line arguments and attempts to contact
   * the Directory Server in order to send it the shutdown request.
   *
   * @param  args       The command-line arguments provided to this program.
   * @param  outStream  The output stream to use for standard output, or
   *                    <CODE>null</CODE> if standard output is not needed.
   * @param  errStream  The output stream to use for standard error, or
   *                    <CODE>null</CODE> if standard error is not needed.
   *
   * @return  An integer value that indicates whether the shutdown request was
   *          accepted by the Directory Server.  A nonzero value should be
   *          interpreted as a failure of some kind.
   */
  public static int stopDS(String[] args, OutputStream outStream,
                           OutputStream errStream)
  {
    PrintStream out;
    if (outStream == null)
    {
      out = NullOutputStream.printStream();
    }
    else
    {
      out = new PrintStream(outStream);
    }
    PrintStream err;
    if (errStream == null)
    {
      err = NullOutputStream.printStream();
    }
    else
    {
      err = new PrintStream(errStream);
    }
    // Define all the arguments that may be used with this program.
    ArgumentParser    argParser = new ArgumentParser(CLASS_NAME, false);
    BooleanArgument   restart;
@@ -240,14 +286,14 @@
      showUsage = new BooleanArgument("showusage", 'H', "help",
                                      MSGID_STOPDS_DESCRIPTION_SHOWUSAGE);
      argParser.addArgument(showUsage);
      argParser.setUsageArgument(showUsage);
      argParser.setUsageArgument(showUsage, out);
    }
    catch (ArgumentException ae)
    {
      int    msgID   = MSGID_STOPDS_CANNOT_INITIALIZE_ARGS;
      String message = getMessage(msgID, ae.getMessage());
      System.err.println(message);
      err.println(message);
      return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
    }
@@ -262,8 +308,8 @@
      int    msgID   = MSGID_STOPDS_ERROR_PARSING_ARGS;
      String message = getMessage(msgID, ae.getMessage());
      System.err.println(message);
      System.err.println(argParser.getUsage());
      err.println(message);
      err.println(argParser.getUsage());
      return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
    }
@@ -283,7 +329,7 @@
      int    msgID   = MSGID_STOPDS_MUTUALLY_EXCLUSIVE_ARGUMENTS;
      String message = getMessage(msgID, bindPW.getLongIdentifier(),
                                  bindPWFile.getLongIdentifier());
      System.err.println(message);
      err.println(message);
      return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
    }
@@ -295,7 +341,7 @@
      int    msgID   = MSGID_STOPDS_MUTUALLY_EXCLUSIVE_ARGUMENTS;
      String message = getMessage(msgID, keyStorePW.getLongIdentifier(),
                                  keyStorePWFile.getLongIdentifier());
      System.err.println(message);
      err.println(message);
      return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
    }
@@ -307,7 +353,7 @@
      int    msgID   = MSGID_STOPDS_MUTUALLY_EXCLUSIVE_ARGUMENTS;
      String message = getMessage(msgID, trustStorePW.getLongIdentifier(),
                                  trustStorePWFile.getLongIdentifier());
      System.err.println(message);
      err.println(message);
      return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
    }
@@ -332,7 +378,7 @@
        {
          int    msgID   = MSGID_STOPDS_CANNOT_DECODE_STOP_TIME;
          String message = getMessage(msgID);
          System.err.println(message);
          err.println(message);
          return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
        }
      }
@@ -350,7 +396,7 @@
        {
          int    msgID   = MSGID_STOPDS_CANNOT_DECODE_STOP_TIME;
          String message = getMessage(msgID);
          System.err.println(message);
          err.println(message);
          return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
        }
      }
@@ -373,7 +419,7 @@
        int    msgID   = MSGID_STOPDS_MUTUALLY_EXCLUSIVE_ARGUMENTS;
        String message = getMessage(msgID, useSSL.getLongIdentifier(),
                                    useStartTLS.getLongIdentifier());
        System.err.println(message);
        err.println(message);
        return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
      }
      else
@@ -405,7 +451,7 @@
      {
        int    msgID   = MSGID_STOPDS_CANNOT_INITIALIZE_SSL;
        String message = getMessage(msgID, sce.getMessage());
        System.err.println(message);
        err.println(message);
        return LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR;
      }
    }
@@ -425,7 +471,7 @@
        {
          int    msgID   = MSGID_STOPDS_CANNOT_PARSE_SASL_OPTION;
          String message = getMessage(msgID, s);
          System.err.println(message);
          err.println(message);
          return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
        }
        else
@@ -448,7 +494,7 @@
      {
        int    msgID   = MSGID_STOPDS_NO_SASL_MECHANISM;
        String message = getMessage(msgID);
        System.err.println(message);
        err.println(message);
        return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
      }
@@ -467,7 +513,7 @@
    try
    {
      connection = new LDAPConnection(host.getValue(), port.getIntValue(),
                                      connectionOptions);
                                      connectionOptions, out, err);
      connection.connectToHost(bindDN.getValue(), bindPW.getValue(),
                               nextMessageID);
    }
@@ -476,14 +522,14 @@
      int    msgID   = MSGID_STOPDS_CANNOT_DETERMINE_PORT;
      String message = getMessage(msgID, port.getLongIdentifier(),
                                  ae.getMessage());
      System.err.println(message);
      err.println(message);
      return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
    }
    catch (LDAPConnectionException lce)
    {
      int    msgID   = MSGID_STOPDS_CANNOT_CONNECT;
      String message = getMessage(msgID, lce.getMessage());
      System.err.println(message);
      err.println(message);
      return LDAPResultCode.CLIENT_SIDE_CONNECT_ERROR;
    }
@@ -567,7 +613,7 @@
      {
        int    msgID   = MSGID_STOPDS_UNEXPECTED_CONNECTION_CLOSURE;
        String message = getMessage(msgID);
        System.err.println(message);
        err.println(message);
        return LDAPResultCode.CLIENT_SIDE_SERVER_DOWN;
      }
@@ -577,21 +623,21 @@
    {
      int    msgID   = MSGID_STOPDS_IO_ERROR;
      String message = getMessage(msgID, String.valueOf(ioe));
      System.err.println(message);
      err.println(message);
      return LDAPResultCode.CLIENT_SIDE_SERVER_DOWN;
    }
    catch (ASN1Exception ae)
    {
      int    msgID   = MSGID_STOPDS_DECODE_ERROR;
      String message = getMessage(msgID, ae.getMessage());
      System.err.println(message);
      err.println(message);
      return LDAPResultCode.CLIENT_SIDE_DECODING_ERROR;
    }
    catch (LDAPException le)
    {
      int    msgID   = MSGID_STOPDS_DECODE_ERROR;
      String message = getMessage(msgID, le.getMessage());
      System.err.println(message);
      err.println(message);
      return LDAPResultCode.CLIENT_SIDE_DECODING_ERROR;
    }
@@ -613,7 +659,7 @@
          String message = extendedResponse.getErrorMessage();
          if (message != null)
          {
            System.err.println(message);
            err.println(message);
          }
          return extendedResponse.getResultCode();
@@ -623,7 +669,7 @@
      int    msgID   = MSGID_STOPDS_INVALID_RESPONSE_TYPE;
      String message = getMessage(msgID, responseMessage.getProtocolOpName());
      System.err.println(message);
      err.println(message);
      return LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR;
    }
@@ -633,7 +679,7 @@
    String errorMessage = addResponse.getErrorMessage();
    if (errorMessage != null)
    {
      System.err.println(errorMessage);
      err.println(errorMessage);
    }
    return addResponse.getResultCode();
opends/src/server/org/opends/server/types/NullOutputStream.java
New file
@@ -0,0 +1,152 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying * information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 */
package org.opends.server.types;
import java.io.OutputStream;
import java.io.PrintStream;
/**
 * This class defines a custom output stream that simply discards any
 * data written to it.
 */
public class NullOutputStream
       extends OutputStream
{
  /**
   * The singleton instance for this class.
   */
  private static final NullOutputStream instance =
       new NullOutputStream();
  /**
   * The singleton print stream tied to the null output stream.
   */
  private static final PrintStream printStream =
       new PrintStream(instance);
  /**
   * Retrieves an instance of this null output stream.
   *
   * @return  An instance of this null output stream.
   */
  public static NullOutputStream instance()
  {
    return instance;
  }
  /**
   * Retrieves a print stream using this null output stream.
   *
   * @return  A print stream using this null output stream.
   */
  public static PrintStream printStream()
  {
    return printStream;
  }
  /**
   * Creates a new instance of this null output stream.
   */
  private NullOutputStream()
  {
    // No implementation is required.
  }
  /**
   * Closes the output stream.  This has no effect.
   */
  public void close()
  {
    // No implementation is required.
  }
  /**
   * Flushes the output stream.  This has no effect.
   */
  public void flush()
  {
    // No implementation is required.
  }
  /**
   * Writes the provided data to this output stream.  This has no
   * effect.
   *
   * @param  b  The byte array containing the data to be written.
   */
  public void write(byte[] b)
  {
    // No implementation is required.
  }
  /**
   * Writes the provided data to this output stream.  This has no
   * effect.
   *
   * @param  b    The byte array containing the data to be written.
   * @param  off  The offset at which the real data begins.
   * @param  len  The number of bytes to be written.
   */
  public void write(byte[] b, int off, int len)
  {
    // No implementation is required.
  }
  /**
   * Writes the provided byte to this output stream.  This has no
   * effect.
   *
   * @param  b  The byte to be written.
   */
  public void write(int b)
  {
    // No implementation is required.
  }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/PlainSASLMechanismHandlerTestCase.java
@@ -41,6 +41,7 @@
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.protocols.ldap.LDAPFilter;
import org.opends.server.tools.LDAPSearch;
import org.opends.server.types.AuthenticationInfo;
import org.opends.server.types.ByteString;
import org.opends.server.types.DN;
@@ -413,6 +414,34 @@
  /**
   * Ensures that SASL PLAIN authentication works over LDAP as well as via the
   * internal protocol.  The authentication will be performed as the root user.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testSASLPlainOverLDAP()
         throws Exception
  {
    String[] args =
    {
      "-h", "127.0.0.1",
      "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
      "-o", "mech=PLAIN",
      "-o", "authid=dn:cn=Directory Manager",
      "-w", "password",
      "-b", "",
      "-s", "base",
      "(objectClass=*)",
      "1.1"
    };
    assertEquals(LDAPSearch.mainSearch(args, false, null, null), 0);
  }
  /**
   * Retrieves sets of invalid credentials that will not succeed when using
   * SASL PLAIN.
   *