/**
   * 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;
  }