/**
  * Creates a connection from information provided.
  *
  * @param host of the server
  * @param port of the server
  * @param bindDN with which to connect
  * @param bindPw with which to connect
  * @param options with which to connect
  * @param timeout the timeout to establish the connection in milliseconds. Use {@code 0} to
  *     express no timeout
  * @param out stream to write messages
  * @param err stream to write error messages
  * @return LDAPConnection created by this class from parsed arguments
  * @throws LDAPConnectionException if there was a problem connecting to the server indicated by
  *     the input arguments
  */
 public LDAPConnection connect(
     String host,
     int port,
     String bindDN,
     String bindPw,
     LDAPConnectionOptions options,
     int timeout,
     PrintStream out,
     PrintStream err)
     throws LDAPConnectionException {
   // Attempt to connect and authenticate to the Directory Server.
   AtomicInteger nextMessageID = new AtomicInteger(1);
   LDAPConnection connection = new LDAPConnection(host, port, options, out, err);
   connection.connectToHost(bindDN, bindPw, nextMessageID, timeout);
   return connection;
 }
  /**
   * Perform the LDAP EXTENDED operation and send the result back to the client.
   *
   * @param objFactory The object factory for this operation.
   * @param extendedRequest The extended request for this operation.
   * @param controls Any required controls (e.g. for proxy authz).
   * @return The result of the extended operation.
   * @throws IOException If an I/O problem occurs.
   * @throws LDAPException If an error occurs while interacting with an LDAP element.
   * @throws ASN1Exception If an error occurs while interacting with an ASN.1 element.
   */
  public ExtendedResponse doOperation(
      ObjectFactory objFactory,
      ExtendedRequest extendedRequest,
      List<org.opends.server.types.Control> controls)
      throws IOException, LDAPException, ASN1Exception {
    ExtendedResponse extendedResponse = objFactory.createExtendedResponse();
    extendedResponse.setRequestID(extendedRequest.getRequestID());

    String requestName = extendedRequest.getRequestName();
    Object value = extendedRequest.getRequestValue();
    ByteString asnValue = ByteStringUtility.convertValue(value);

    // Create and send the LDAP request to the server.
    ProtocolOp op = new ExtendedRequestProtocolOp(requestName, asnValue);
    LDAPMessage msg = new LDAPMessage(DSMLServlet.nextMessageID(), op, controls);
    connection.getLDAPWriter().writeMessage(msg);

    // Read and decode the LDAP response from the server.
    LDAPMessage responseMessage = connection.getLDAPReader().readMessage();

    ExtendedResponseProtocolOp extendedOp = responseMessage.getExtendedResponseProtocolOp();
    int resultCode = extendedOp.getResultCode();
    Message errorMessage = extendedOp.getErrorMessage();

    // Set the result code and error message for the DSML response.
    extendedResponse.setResponseName(extendedOp.getOID());

    ByteString rawValue = extendedOp.getValue();
    value = null;
    if (rawValue != null) {
      if (responseIsString(requestName)) {
        value = rawValue.toString();
      } else {
        value = rawValue.toByteArray();
      }
    }
    extendedResponse.setResponse(value);
    extendedResponse.setErrorMessage(errorMessage != null ? errorMessage.toString() : null);
    ResultCode code = ResultCodeFactory.create(objFactory, resultCode);
    extendedResponse.setResultCode(code);

    return extendedResponse;
  }