From 9f0eb1a26745e51dc39184882d542583ba4ab7e5 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Wed, 14 Mar 2007 20:32:37 +0000
Subject: [PATCH] Update the LDAP client tools so that they provide error messages in a more readable format.  They can now generate up to four lines of output in the following order:

---
 opends/src/server/org/opends/server/tools/LDAPPasswordModify.java        |    2 
 opends/src/server/org/opends/server/messages/ToolMessages.java           |   64 ++++--
 opends/src/server/org/opends/server/protocols/ldap/LDAPException.java    |  121 +++++++++++
 opends/src/server/org/opends/server/tools/LDAPAuthenticationHandler.java |   81 ++++---
 opends/src/server/org/opends/server/tools/LDAPModify.java                |   33 ++-
 opends/src/server/org/opends/server/tools/LDAPDelete.java                |   23 +
 opends/src/server/org/opends/server/tools/LDAPConnectionException.java   |  115 +++++++++--
 opends/src/server/org/opends/server/tools/LDAPToolUtils.java             |   43 ++++
 opends/src/server/org/opends/server/tools/LDAPCompare.java               |   23 +
 opends/src/server/org/opends/server/tools/LDAPConnection.java            |   30 +-
 opends/src/server/org/opends/server/tools/LDAPSearch.java                |   21 +
 11 files changed, 421 insertions(+), 135 deletions(-)

diff --git a/opends/src/server/org/opends/server/messages/ToolMessages.java b/opends/src/server/org/opends/server/messages/ToolMessages.java
index e76e812..17bb407 100644
--- a/opends/src/server/org/opends/server/messages/ToolMessages.java
+++ b/opends/src/server/org/opends/server/messages/ToolMessages.java
@@ -1364,9 +1364,7 @@
 
   /**
    * The message ID for the message that will be used if the simple bind attempt
-   * fails.  This takes three arguments, which are the integer and string
-   * representations of the result code and the error message from the bind
-   * response.
+   * fails.  This does not take any arguments.
    */
   public static final int MSGID_LDAPAUTH_SIMPLE_BIND_FAILED =
        CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 141;
@@ -1426,9 +1424,7 @@
 
   /**
    * The message ID for the message that will be used if a SASL bind attempt
-   * fails.  This takes four arguments, which are the SASL mechanism name,
-   * integer and string representations of the result code and the error message
-   * from the bind response.
+   * fails.  This takes a single argument, which is the SASL mechanism name.
    */
   public static final int MSGID_LDAPAUTH_SASL_BIND_FAILED =
        CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 147;
@@ -1920,9 +1916,7 @@
   /**
    * The message ID for the message that will be used if the Directory Server
    * sent a bind response that was neither "success" nor "SASL bind in
-   * progress".  This takes three arguments, which are the result code, a
-   * string representation of the result code, and the error message from the
-   * bind response (if any).
+   * progress".  This does not take any arguments.
    */
   public static final int MSGID_LDAPAUTH_GSSAPI_BIND_FAILED =
        CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 195;
@@ -2012,9 +2006,7 @@
 
   /**
    * The message ID for the message that will be used if the "Who Am I?" request
-   * was rejected by the server.  This takes three arguments, which are the
-   * result code from the response, a string representation of that result code,
-   * and the error message from the response.
+   * was rejected by the server.  This does not take any arguments.
    */
   public static final int MSGID_LDAPAUTH_WHOAMI_FAILED =
        CATEGORY_MASK_TOOLS | SEVERITY_MASK_MILD_ERROR | 204;
@@ -7694,6 +7686,34 @@
        CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 809;
 
   /**
+   * The message ID for the message that will be used to print the result code
+   * for an error encountered in a client tool.  This takes two arguments,
+   * which are the integer and string representations of the result code.
+   */
+  public static final int MSGID_TOOL_RESULT_CODE =
+       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 810;
+
+  /**
+   * The message ID for the message that will be used to print the error message
+   * or additional information string returned by the server for an error
+   * encountered in a client tool.  This takes a single argument, which is the
+   * error message string.
+   */
+  public static final int MSGID_TOOL_ERROR_MESSAGE =
+       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 811;
+
+  /**
+   * The message ID for the message that will be used to print the matched DN
+   * returned by the server for an error  encountered in a client tool.  This
+   * takes a single argument, which is the string representation of the matched
+   * DN.
+   */
+  public static final int MSGID_TOOL_MATCHED_DN =
+       CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 812;
+
+
+
+  /**
    * Associates a set of generic messages with the message IDs defined in this
    * class.
    */
@@ -8101,7 +8121,7 @@
     registerMessage(MSGID_PROCESSING_OPERATION,
                     "Processing %s request for %s.");
     registerMessage(MSGID_OPERATION_FAILED,
-                    "%s operation failed for DN %s. %s.");
+                    "%s operation failed.");
     registerMessage(MSGID_OPERATION_SUCCESSFUL,
                     "%s operation successful for DN %s.");
     registerMessage(MSGID_PROCESSING_COMPARE_OPERATION,
@@ -8239,8 +8259,7 @@
                     "The Directory Server sent an unexpected response " +
                     "message to the client:  %s.");
     registerMessage(MSGID_LDAPAUTH_SIMPLE_BIND_FAILED,
-                    "The simple bind attempt failed:  result code %d (%s), " +
-                    "error message \"%s\".");
+                    "The simple bind attempt failed.");
     registerMessage(MSGID_LDAPAUTH_NO_SASL_MECHANISM,
                     "A SASL bind was requested but no SASL mechanism was " +
                     "specified.");
@@ -8256,8 +8275,7 @@
     registerMessage(MSGID_LDAPAUTH_CANNOT_SEND_SASL_BIND,
                     "Cannot send the SASL %S bind request:  %s.");
     registerMessage(MSGID_LDAPAUTH_SASL_BIND_FAILED,
-                    "The SASL %s bind attempt failed:  result code %d (%s), " +
-                    "error message \"%s\".");
+                    "The SASL %s bind attempt failed.");
     registerMessage(MSGID_LDAPAUTH_NO_SASL_PROPERTIES,
                     "No SASL properties were provided for use with the %s " +
                     "mechanism.");
@@ -8425,8 +8443,7 @@
                     "response to the client even though the client does not " +
                     "believe that the GSSAPI negotiation is complete.");
     registerMessage(MSGID_LDAPAUTH_GSSAPI_BIND_FAILED,
-                    "The GSSAPI bind attempt failed.  The result code was %d " +
-                    "(%s), and the error message was \"%s\".");
+                    "The GSSAPI bind attempt failed.");
     registerMessage(MSGID_LDAPAUTH_NONSASL_CALLBACK_INVOCATION,
                     "The LDAPAuthenticationHandler.handle() method was " +
                     "called for a non-SASL bind.  The backtrace for this " +
@@ -8449,8 +8466,7 @@
                     "Server:  %s.");
     registerMessage(MSGID_LDAPAUTH_WHOAMI_FAILED,
                     "The 'Who Am I?' request was rejected by the Directory " +
-                    "Server with a result code of %d (%s) and and error " +
-                    "message of \"%s\".");
+                    "Server.");
 
 
     registerMessage(MSGID_DESCRIPTION_INVALID_VERSION,
@@ -9894,6 +9910,12 @@
     registerMessage(MSGID_TOOL_SASLEXTERNAL_NEEDS_KEYSTORE,
                     "SASL EXTERNAL authentication may only be used if a " +
                     "client certificate keystore is specified.");
+    registerMessage(MSGID_TOOL_RESULT_CODE,
+                    "Result Code:  %d (%s)");
+    registerMessage(MSGID_TOOL_ERROR_MESSAGE,
+                    "Additional Information:  %s");
+    registerMessage(MSGID_TOOL_MATCHED_DN,
+                    "Matched DN:  %s");
 
 
     registerMessage(MSGID_BACKUPDB_TOOL_DESCRIPTION,
diff --git a/opends/src/server/org/opends/server/protocols/ldap/LDAPException.java b/opends/src/server/org/opends/server/protocols/ldap/LDAPException.java
index 83fef46..2adf8a2 100644
--- a/opends/src/server/org/opends/server/protocols/ldap/LDAPException.java
+++ b/opends/src/server/org/opends/server/protocols/ldap/LDAPException.java
@@ -28,6 +28,7 @@
 
 
 
+import org.opends.server.types.DN;
 
 
 
@@ -38,9 +39,6 @@
 public class LDAPException
        extends Exception
 {
-
-
-
   /**
    * The serial version identifier required to satisfy the compiler because this
    * class extends <CODE>java.lang.Exception</CODE>, which implements the
@@ -52,12 +50,17 @@
 
 
 
-  // The message ID for the message associated with this initialization
-  // exception.
-  private int messageID;
+  // The matched DN associated with this LDAP exception.
+  private final DN matchedDN;
+
+  // The message ID for the message associated with this LDAP exception.
+  private final int messageID;
 
   // The LDAP result code associated with this exception.
-  private int resultCode;
+  private final int resultCode;
+
+  // The server-provided error message for this LDAP exception.
+  private final String errorMessage;
 
 
 
@@ -72,9 +75,33 @@
   {
     super(message);
 
-
     this.resultCode = resultCode;
     this.messageID  = messageID;
+
+    errorMessage = null;
+    matchedDN    = null;
+  }
+
+
+
+  /**
+   * Creates a new LDAP exception with the provided message.
+   *
+   * @param  resultCode    The LDAP result code associated with this exception.
+   * @param  errorMessage  The server-provided error message.
+   * @param  messageID     The unique identifier for the associated message.
+   * @param  message       The message that explains the problem that occurred.
+   */
+  public LDAPException(int resultCode, String errorMessage, int messageID,
+                       String message)
+  {
+    super(message);
+
+    this.resultCode   = resultCode;
+    this.errorMessage = errorMessage;
+    this.messageID    = messageID;
+
+    matchedDN    = null;
   }
 
 
@@ -93,9 +120,59 @@
   {
     super(message, cause);
 
-
     this.resultCode = resultCode;
     this.messageID  = messageID;
+
+    errorMessage = null;
+    matchedDN    = null;
+  }
+
+
+
+  /**
+   * Creates a new LDAP exception with the provided message and root cause.
+   *
+   * @param  resultCode    The LDAP result code associated with this exception.
+   * @param  errorMessage  The server-provided error message.
+   * @param  messageID     The unique identifier for the associated message.
+   * @param  message       The message that explains the problem that occurred.
+   * @param  cause         The exception that was caught to trigger this
+   *                       exception.
+   */
+  public LDAPException(int resultCode, String errorMessage, int messageID,
+                       String message, Throwable cause)
+  {
+    super(message, cause);
+
+    this.resultCode   = resultCode;
+    this.errorMessage = errorMessage;
+    this.messageID    = messageID;
+
+    matchedDN    = null;
+  }
+
+
+
+  /**
+   * Creates a new LDAP exception with the provided message and root cause.
+   *
+   * @param  resultCode    The LDAP result code associated with this exception.
+   * @param  errorMessage  The server-provided error message.
+   * @param  messageID     The unique identifier for the associated message.
+   * @param  message       The message that explains the problem that occurred.
+   * @param  matchedDN     The matched DN returned by the server.
+   * @param  cause         The exception that was caught to trigger this
+   *                       exception.
+   */
+  public LDAPException(int resultCode, String errorMessage, int messageID,
+                       String message, DN matchedDN, Throwable cause)
+  {
+    super(message, cause);
+
+    this.resultCode   = resultCode;
+    this.errorMessage = errorMessage;
+    this.messageID    = messageID;
+    this.matchedDN    = matchedDN;
   }
 
 
@@ -113,6 +190,19 @@
 
 
   /**
+   * Retrieves the server-provided error message for this exception.
+   *
+   * @return  The server-provided error message for this exception, or
+   *          {@code null} if none was given.
+   */
+  public String getErrorMessage()
+  {
+    return errorMessage;
+  }
+
+
+
+  /**
    * Retrieves the unique identifier for the associated message.
    *
    * @return  The unique identifier for the associated message.
@@ -121,5 +211,18 @@
   {
     return messageID;
   }
+
+
+
+  /**
+   * Retrieves the matched DN for this exception.
+   *
+   * @return  The matched DN for this exception, or {@code null} if there is
+   *          none.
+   */
+  public DN getMatchedDN()
+  {
+    return matchedDN;
+  }
 }
 
diff --git a/opends/src/server/org/opends/server/tools/LDAPAuthenticationHandler.java b/opends/src/server/org/opends/server/tools/LDAPAuthenticationHandler.java
index 39387bf..dba22bc 100644
--- a/opends/src/server/org/opends/server/tools/LDAPAuthenticationHandler.java
+++ b/opends/src/server/org/opends/server/tools/LDAPAuthenticationHandler.java
@@ -448,10 +448,9 @@
     // FIXME -- Add support for referrals.
 
     int    msgID   = MSGID_LDAPAUTH_SIMPLE_BIND_FAILED;
-    String message = getMessage(msgID, resultCode,
-                                LDAPResultCode.toString(resultCode),
-                                bindResponse.getErrorMessage());
-    throw new LDAPException(bindResponse.getResultCode(), msgID, message);
+    String message = getMessage(msgID);
+    throw new LDAPException(resultCode, bindResponse.getErrorMessage(),
+                            msgID, message, bindResponse.getMatchedDN(), null);
   }
 
 
@@ -774,10 +773,9 @@
     // FIXME -- Add support for referrals.
 
     int    msgID   = MSGID_LDAPAUTH_SASL_BIND_FAILED;
-    String message = getMessage(msgID, SASL_MECHANISM_ANONYMOUS, resultCode,
-                                LDAPResultCode.toString(resultCode),
-                                bindResponse.getErrorMessage());
-    throw new LDAPException(bindResponse.getResultCode(), msgID, message);
+    String message = getMessage(msgID, SASL_MECHANISM_ANONYMOUS);
+    throw new LDAPException(resultCode, bindResponse.getErrorMessage(),
+                            msgID, message, bindResponse.getMatchedDN(), null);
   }
 
 
@@ -1038,11 +1036,18 @@
     int resultCode1 = bindResponse1.getResultCode();
     if (resultCode1 != LDAPResultCode.SASL_BIND_IN_PROGRESS)
     {
+      String errorMessage = bindResponse1.getErrorMessage();
+      if (errorMessage == null)
+      {
+        errorMessage = "";
+      }
+
       int    msgID   = MSGID_LDAPAUTH_UNEXPECTED_INITIAL_BIND_RESPONSE;
       String message = getMessage(msgID, SASL_MECHANISM_CRAM_MD5, resultCode1,
                                   LDAPResultCode.toString(resultCode1),
-                                  bindResponse1.getErrorMessage());
-      throw new LDAPException(resultCode1, msgID, message);
+                                  errorMessage);
+      throw new LDAPException(resultCode1, errorMessage, msgID, message,
+                              bindResponse1.getMatchedDN(), null);
     }
 
 
@@ -1205,10 +1210,9 @@
     // FIXME -- Add support for referrals.
 
     int    msgID   = MSGID_LDAPAUTH_SASL_BIND_FAILED;
-    String message = getMessage(msgID, SASL_MECHANISM_CRAM_MD5, resultCode2,
-                                LDAPResultCode.toString(resultCode2),
-                                bindResponse2.getErrorMessage());
-    throw new LDAPException(bindResponse2.getResultCode(), msgID, message);
+    String message = getMessage(msgID, SASL_MECHANISM_CRAM_MD5);
+    throw new LDAPException(resultCode2, bindResponse2.getErrorMessage(),
+                            msgID, message, bindResponse2.getMatchedDN(), null);
   }
 
 
@@ -1659,11 +1663,18 @@
     int resultCode1 = bindResponse1.getResultCode();
     if (resultCode1 != LDAPResultCode.SASL_BIND_IN_PROGRESS)
     {
+      String errorMessage = bindResponse1.getErrorMessage();
+      if (errorMessage == null)
+      {
+        errorMessage = "";
+      }
+
       int    msgID   = MSGID_LDAPAUTH_UNEXPECTED_INITIAL_BIND_RESPONSE;
       String message = getMessage(msgID, SASL_MECHANISM_DIGEST_MD5, resultCode1,
                                   LDAPResultCode.toString(resultCode1),
-                                  bindResponse1.getErrorMessage());
-      throw new LDAPException(resultCode1, msgID, message);
+                                  errorMessage);
+      throw new LDAPException(resultCode1, errorMessage, msgID, message,
+                              bindResponse1.getMatchedDN(), null);
     }
 
 
@@ -1990,10 +2001,10 @@
       // FIXME -- Add support for referrals.
 
       int    msgID   = MSGID_LDAPAUTH_SASL_BIND_FAILED;
-      String message = getMessage(msgID, SASL_MECHANISM_DIGEST_MD5, resultCode2,
-                                  LDAPResultCode.toString(resultCode2),
-                                  bindResponse2.getErrorMessage());
-      throw new LDAPException(bindResponse2.getResultCode(), msgID, message);
+      String message = getMessage(msgID, SASL_MECHANISM_DIGEST_MD5);
+      throw new LDAPException(resultCode2, bindResponse2.getErrorMessage(),
+                              msgID, message, bindResponse2.getMatchedDN(),
+                              null);
     }
 
 
@@ -2672,10 +2683,9 @@
     // FIXME -- Add support for referrals.
 
     int    msgID   = MSGID_LDAPAUTH_SASL_BIND_FAILED;
-    String message = getMessage(msgID, SASL_MECHANISM_EXTERNAL, resultCode,
-                                LDAPResultCode.toString(resultCode),
-                                bindResponse.getErrorMessage());
-    throw new LDAPException(bindResponse.getResultCode(), msgID, message);
+    String message = getMessage(msgID, SASL_MECHANISM_EXTERNAL);
+    throw new LDAPException(resultCode, bindResponse.getErrorMessage(),
+                            msgID, message, bindResponse.getMatchedDN(), null);
   }
 
 
@@ -3296,10 +3306,9 @@
     // FIXME -- Add support for referrals.
 
     int    msgID   = MSGID_LDAPAUTH_SASL_BIND_FAILED;
-    String message = getMessage(msgID, SASL_MECHANISM_PLAIN, resultCode,
-                                LDAPResultCode.toString(resultCode),
-                                bindResponse.getErrorMessage());
-    throw new LDAPException(bindResponse.getResultCode(), msgID, message);
+    String message = getMessage(msgID, SASL_MECHANISM_PLAIN);
+    throw new LDAPException(resultCode, bindResponse.getErrorMessage(),
+                            msgID, message, bindResponse.getMatchedDN(), null);
   }
 
 
@@ -3716,10 +3725,10 @@
         {
           // This is an error.
           int    msgID   = MSGID_LDAPAUTH_GSSAPI_BIND_FAILED;
-          String message = getMessage(msgID, resultCode,
-                                      LDAPResultCode.toString(resultCode),
-                                      bindResponse.getErrorMessage());
-          throw new LDAPException(resultCode, msgID, message);
+          String message = getMessage(msgID);
+          throw new LDAPException(resultCode, bindResponse.getErrorMessage(),
+                                  msgID, message, bindResponse.getMatchedDN(),
+                                  null);
         }
       }
     }
@@ -3916,10 +3925,10 @@
     if (resultCode != LDAPResultCode.SUCCESS)
     {
       int msgID = MSGID_LDAPAUTH_WHOAMI_FAILED;
-      String message = getMessage(msgID, resultCode,
-                                  LDAPResultCode.toString(resultCode),
-                                  extendedResponse.getErrorMessage());
-      throw new LDAPException(resultCode, msgID, message);
+      String message = getMessage(msgID);
+      throw new LDAPException(resultCode, extendedResponse.getErrorMessage(),
+                              msgID, message, extendedResponse.getMatchedDN(),
+                              null);
     }
 
 
diff --git a/opends/src/server/org/opends/server/tools/LDAPCompare.java b/opends/src/server/org/opends/server/tools/LDAPCompare.java
index c9cc832..75a82ec 100644
--- a/opends/src/server/org/opends/server/tools/LDAPCompare.java
+++ b/opends/src/server/org/opends/server/tools/LDAPCompare.java
@@ -221,8 +221,9 @@
         else
         {
           msgID = MSGID_OPERATION_FAILED;
-          String msg = getMessage(msgID, "COMPARE", line, ae.getMessage());
+          String msg = getMessage(msgID, "COMPARE");
           err.println(wrapText(msg, MAX_LINE_WIDTH));
+          err.println(wrapText(ae.getMessage(), MAX_LINE_WIDTH));
           return;
         }
       }
@@ -236,8 +237,9 @@
          && !compareOptions.continueOnError())
       {
         msgID = MSGID_OPERATION_FAILED;
-        String msg = getMessage(msgID, "COMPARE", line, errorMessage);
-        throw new LDAPException(resultCode, msgID, msg);
+        String msg = getMessage(msgID, "COMPARE");
+        throw new LDAPException(resultCode, errorMessage, msgID, msg,
+                                op.getMatchedDN(), null);
       } else
       {
         if(resultCode == COMPARE_FALSE)
@@ -251,8 +253,9 @@
         } else
         {
           msgID = MSGID_OPERATION_FAILED;
-          String msg = getMessage(msgID, "COMPARE", line, errorMessage);
-          err.println(wrapText(msg, MAX_LINE_WIDTH));
+          String msg = getMessage(msgID, "COMPARE");
+          LDAPToolUtils.printErrorMessage(err, msg, resultCode, errorMessage,
+                                          op.getMatchedDN());
         }
       }
     }
@@ -868,7 +871,8 @@
       {
         debugCaught(DebugLogLevel.ERROR, le);
       }
-      err.println(wrapText(le.getMessage(), MAX_LINE_WIDTH));
+      LDAPToolUtils.printErrorMessage(err, le.getMessage(), le.getResultCode(),
+                                      le.getErrorMessage(), le.getMatchedDN());
       int code = le.getResultCode();
       return code;
     } catch(LDAPConnectionException lce)
@@ -877,8 +881,11 @@
       {
         debugCaught(DebugLogLevel.ERROR, lce);
       }
-      err.println(wrapText(lce.getMessage(), MAX_LINE_WIDTH));
-      int code = lce.getErrorCode();
+      LDAPToolUtils.printErrorMessage(err, lce.getMessage(),
+                                      lce.getResultCode(),
+                                      lce.getErrorMessage(),
+                                      lce.getMatchedDN());
+      int code = lce.getResultCode();
       return code;
     } catch(Exception e)
     {
diff --git a/opends/src/server/org/opends/server/tools/LDAPConnection.java b/opends/src/server/org/opends/server/tools/LDAPConnection.java
index 738f174..a7b5575 100644
--- a/opends/src/server/org/opends/server/tools/LDAPConnection.java
+++ b/opends/src/server/org/opends/server/tools/LDAPConnection.java
@@ -44,6 +44,7 @@
 import org.opends.server.protocols.ldap.ExtendedRequestProtocolOp;
 import org.opends.server.protocols.ldap.ExtendedResponseProtocolOp;
 import org.opends.server.protocols.ldap.LDAPControl;
+import org.opends.server.protocols.ldap.LDAPException;
 import org.opends.server.protocols.ldap.LDAPMessage;
 import org.opends.server.protocols.ldap.UnbindRequestProtocolOp;
 import org.opends.server.types.Control;
@@ -166,12 +167,14 @@
       {
         int msgID = MSGID_RESULT_CLIENT_SIDE_CONNECT_ERROR;
         String msg = getMessage(msgID);
-        throw new LDAPConnectionException(msg, CLIENT_SIDE_CONNECT_ERROR, uhe);
+        throw new LDAPConnectionException(msg, CLIENT_SIDE_CONNECT_ERROR, null,
+                                          uhe);
       } catch(ConnectException ce)
       {
         int msgID = MSGID_RESULT_CLIENT_SIDE_CONNECT_ERROR;
         String msg = getMessage(msgID);
-        throw new LDAPConnectionException(msg, CLIENT_SIDE_CONNECT_ERROR, ce);
+        throw new LDAPConnectionException(msg, CLIENT_SIDE_CONNECT_ERROR, null,
+                                          ce);
       } catch(Exception ex)
       {
         if (debugEnabled())
@@ -205,12 +208,9 @@
       resultCode = res.getResultCode();
       if(resultCode != SUCCESS)
       {
-        String message = res.getErrorMessage();
-        if(message == null)
-        {
-          message = "Response code:" + resultCode;
-        }
-        throw new LDAPConnectionException(message);
+        throw new LDAPConnectionException(res.getErrorMessage(), resultCode,
+                                          res.getErrorMessage(),
+                                          res.getMatchedDN(), null);
       }
     }
     SSLConnectionFactory sslConnectionFactory =
@@ -238,12 +238,14 @@
     {
       int msgID = MSGID_RESULT_CLIENT_SIDE_CONNECT_ERROR;
       String msg = getMessage(msgID);
-      throw new LDAPConnectionException(msg, CLIENT_SIDE_CONNECT_ERROR, uhe);
+      throw new LDAPConnectionException(msg, CLIENT_SIDE_CONNECT_ERROR, null,
+                                        uhe);
     } catch(ConnectException ce)
     {
       int msgID = MSGID_RESULT_CLIENT_SIDE_CONNECT_ERROR;
       String msg = getMessage(msgID);
-      throw new LDAPConnectionException(msg, CLIENT_SIDE_CONNECT_ERROR, ce);
+      throw new LDAPConnectionException(msg, CLIENT_SIDE_CONNECT_ERROR, null,
+                                        ce);
     } catch(Exception ex2)
     {
       if (debugEnabled())
@@ -406,7 +408,13 @@
       {
         debugCaught(DebugLogLevel.ERROR, ce);
       }
-      throw new LDAPConnectionException(ce.getMessage(), ce.getExitCode(), ce);
+      throw new LDAPConnectionException(ce.getMessage(), ce.getExitCode(),
+                                        null, ce);
+    } catch (LDAPException le)
+    {
+      throw new LDAPConnectionException(le.getMessage(), le.getResultCode(),
+                                        le.getErrorMessage(), le.getMatchedDN(),
+                                        le.getCause());
     } catch(Exception ex)
     {
       if (debugEnabled())
diff --git a/opends/src/server/org/opends/server/tools/LDAPConnectionException.java b/opends/src/server/org/opends/server/tools/LDAPConnectionException.java
index 8756543..68f8de5 100644
--- a/opends/src/server/org/opends/server/tools/LDAPConnectionException.java
+++ b/opends/src/server/org/opends/server/tools/LDAPConnectionException.java
@@ -27,15 +27,15 @@
 package org.opends.server.tools;
 
 
+import org.opends.server.types.DN;
+
+
 /**
  * This class defines an exception that may be thrown during the course of
  * creating an LDAP connection to the server.
  */
 public class LDAPConnectionException extends Exception
 {
-
-
-
   /**
    * The serial version identifier required to satisfy the compiler because this
    * class extends <CODE>java.lang.Exception</CODE>, which implements the
@@ -47,9 +47,22 @@
 
 
   /**
-   * The error code associated with the exception.
+   * The LDAP result code associated with the exception.
    */
-  private int errorCode = 1;
+  private final int resultCode;
+
+
+  /**
+   * The matched DN associated with the exception.
+   */
+  private final DN matchedDN;
+
+
+  /**
+   * The server-provided error message for this exception.
+   */
+  private final String errorMessage;
+
 
   /**
    * Creates a new exception with the provided message.
@@ -60,20 +73,28 @@
   {
     super(message);
 
+    resultCode   = -1;
+    matchedDN    = null;
+    errorMessage = null;
   }
 
 
   /**
    * Creates a new exception with the provided message.
    *
-   * @param  message    The message to use for this exception.
-   * @param  errorCode  The error code for this exception.
+   * @param  message       The message to use for this exception.
+   * @param  resultCode    The result code for this exception.
+   * @param  errorMessage  The server-provided error message for this exception.
    */
-  public LDAPConnectionException(String message, int errorCode)
+  public LDAPConnectionException(String message, int resultCode,
+                                 String errorMessage)
   {
     super(message);
 
-    this.errorCode = errorCode;
+    this.resultCode   = resultCode;
+    this.errorMessage = errorMessage;
+
+    matchedDN = null;
   }
 
 
@@ -89,7 +110,9 @@
   {
     super(message, cause);
 
-
+    resultCode   = -1;
+    matchedDN    = null;
+    errorMessage = null;
   }
 
 
@@ -97,28 +120,80 @@
    * Creates a new exception with the provided message and
    * underlying cause.
    *
-   * @param  message    The message to use for this exception.
-   * @param  errorCode  The error code for this exception.
-   * @param  cause      The underlying cause that triggered this
-   *                    exception.
+   * @param  message       The message to use for this exception.
+   * @param  resultCode    The result code for this exception.
+   * @param  errorMessage  The server-provided error message for this exception.
+   * @param  cause         The underlying cause that triggered this
+   *                       exception.
    */
-  public LDAPConnectionException(String message, int errorCode, Throwable cause)
+  public LDAPConnectionException(String message, int resultCode,
+                                 String errorMessage, Throwable cause)
   {
     super(message, cause);
 
-    this.errorCode = errorCode;
+    this.resultCode   = resultCode;
+    this.errorMessage = errorMessage;
 
+    matchedDN = null;
   }
 
 
   /**
-   * Return the error code associated with this exception.
+   * Creates a new exception with the provided message and
+   * underlying cause.
    *
-   * @return  The error code associated with this exception.
+   * @param  message       The explanation to use for this exception.
+   * @param  resultCode    The result code for this exception.
+   * @param  errorMessage  The server-provided error message for this
+   *                       exception.
+   * @param  matchedDN     The matched DN string for this exception.
+   * @param  cause         The underlying cause that triggered this
+   *                       exception.
    */
-  public int getErrorCode()
+  public LDAPConnectionException(String message, int resultCode,
+                                 String errorMessage, DN matchedDN,
+                                 Throwable cause)
   {
-    return this.errorCode;
+    super(message, cause);
+
+    this.resultCode   = resultCode;
+    this.errorMessage = errorMessage;
+    this.matchedDN    = matchedDN;
+  }
+
+
+  /**
+   * Return the result code associated with this exception.
+   *
+   * @return  The result code associated with this exception, or -1 if none was
+   *          provided.
+   */
+  public int getResultCode()
+  {
+    return this.resultCode;
+  }
+
+
+  /**
+   * Retrieves the server-provided error message associated with this exception.
+   *
+   * @return  The server-provided error message associated with this exception.
+   */
+  public String getErrorMessage()
+  {
+    return this.errorMessage;
+  }
+
+
+  /**
+   * Return the matched DN associated with this exception.
+   *
+   * @return  The matched DN associated with this exception, or {@code null} if
+   *          none was provided.
+   */
+  public DN getMatchedDN()
+  {
+    return this.matchedDN;
   }
 }
 
diff --git a/opends/src/server/org/opends/server/tools/LDAPDelete.java b/opends/src/server/org/opends/server/tools/LDAPDelete.java
index 5d38681..59742a5 100644
--- a/opends/src/server/org/opends/server/tools/LDAPDelete.java
+++ b/opends/src/server/org/opends/server/tools/LDAPDelete.java
@@ -205,8 +205,9 @@
         else
         {
           msgID = MSGID_OPERATION_FAILED;
-          String msg = getMessage(msgID, "DELETE", line, ae.getMessage());
+          String msg = getMessage(msgID, "DELETE");
           err.println(wrapText(msg, MAX_LINE_WIDTH));
+          err.println(wrapText(ae.getMessage(), MAX_LINE_WIDTH));
           return;
         }
       }
@@ -219,15 +220,17 @@
          !deleteOptions.continueOnError())
       {
         msgID = MSGID_OPERATION_FAILED;
-        String msg = getMessage(msgID, "DELETE", line, errorMessage);
-        throw new LDAPException(resultCode, msgID, msg);
+        String msg = getMessage(msgID, "DELETE");
+        throw new LDAPException(resultCode, errorMessage, msgID, msg,
+                                op.getMatchedDN(), null);
       } else
       {
         if(resultCode != SUCCESS && resultCode != REFERRAL)
         {
           msgID = MSGID_OPERATION_FAILED;
-          String msg = getMessage(msgID, "DELETE", line, errorMessage);
-          err.println(wrapText(msg, MAX_LINE_WIDTH));
+          String msg = getMessage(msgID, "DELETE");
+          LDAPToolUtils.printErrorMessage(err, msg, resultCode, errorMessage,
+                                          op.getMatchedDN());
         } else
         {
           msgID = MSGID_OPERATION_SUCCESSFUL;
@@ -746,7 +749,8 @@
       {
         debugCaught(DebugLogLevel.ERROR, le);
       }
-      err.println(wrapText(le.getMessage(), MAX_LINE_WIDTH));
+      LDAPToolUtils.printErrorMessage(err, le.getMessage(), le.getResultCode(),
+                                      le.getErrorMessage(), le.getMatchedDN());
       int code = le.getResultCode();
       return code;
     } catch(LDAPConnectionException lce)
@@ -755,8 +759,11 @@
       {
         debugCaught(DebugLogLevel.ERROR, lce);
       }
-      err.println(wrapText(lce.getMessage(), MAX_LINE_WIDTH));
-      int code = lce.getErrorCode();
+      LDAPToolUtils.printErrorMessage(err, lce.getMessage(),
+                                      lce.getResultCode(),
+                                      lce.getErrorMessage(),
+                                      lce.getMatchedDN());
+      int code = lce.getResultCode();
       return code;
     } catch(Exception e)
     {
diff --git a/opends/src/server/org/opends/server/tools/LDAPModify.java b/opends/src/server/org/opends/server/tools/LDAPModify.java
index 61da732..308a31e 100644
--- a/opends/src/server/org/opends/server/tools/LDAPModify.java
+++ b/opends/src/server/org/opends/server/tools/LDAPModify.java
@@ -59,6 +59,7 @@
 import org.opends.server.protocols.ldap.SearchResultEntryProtocolOp;
 import org.opends.server.protocols.ldap.ProtocolOp;
 import org.opends.server.types.Attribute;
+import org.opends.server.types.DN;
 import org.opends.server.types.LDIFImportConfig;
 import org.opends.server.types.NullOutputStream;
 import org.opends.server.types.DebugLogLevel;
@@ -345,9 +346,9 @@
             debugCaught(DebugLogLevel.ERROR, ae);
           }
           msgID = MSGID_OPERATION_FAILED;
-          String message = getMessage(msgID, operationType, asn1OctetStr,
-                                      ae.getMessage());
+          String message = getMessage(msgID, operationType);
           err.println(wrapText(message, MAX_LINE_WIDTH));
+          err.println(wrapText(ae.getMessage(), MAX_LINE_WIDTH));
           if (!modifyOptions.continueOnError())
           {
             throw new IOException(ae.getMessage());
@@ -357,6 +358,7 @@
 
         int resultCode = 0;
         String errorMessage = null;
+        DN matchedDN = null;
         List<String> referralURLs = null;
         switch(entry.getChangeOperationType())
         {
@@ -365,6 +367,7 @@
               responseMessage.getAddResponseProtocolOp();
             resultCode = addOp.getResultCode();
             errorMessage = addOp.getErrorMessage();
+            matchedDN = addOp.getMatchedDN();
             referralURLs = addOp.getReferralURLs();
             break;
           case DELETE:
@@ -372,6 +375,7 @@
               responseMessage.getDeleteResponseProtocolOp();
             resultCode = delOp.getResultCode();
             errorMessage = delOp.getErrorMessage();
+            matchedDN = delOp.getMatchedDN();
             referralURLs = delOp.getReferralURLs();
             break;
           case MODIFY:
@@ -379,6 +383,7 @@
               responseMessage.getModifyResponseProtocolOp();
             resultCode = modOp.getResultCode();
             errorMessage = modOp.getErrorMessage();
+            matchedDN = modOp.getMatchedDN();
             referralURLs = modOp.getReferralURLs();
             break;
           case MODIFY_DN:
@@ -386,6 +391,7 @@
               responseMessage.getModifyDNResponseProtocolOp();
             resultCode = modDNOp.getResultCode();
             errorMessage = modDNOp.getErrorMessage();
+            matchedDN = modDNOp.getMatchedDN();
             referralURLs = modDNOp.getReferralURLs();
             break;
           default:
@@ -394,20 +400,17 @@
 
         if(resultCode != SUCCESS && resultCode != REFERRAL)
         {
-          if(errorMessage == null)
-          {
-            errorMessage = "Result code:" + resultCode;
-          }
           msgID = MSGID_OPERATION_FAILED;
-          String msg = getMessage(msgID, operationType, asn1OctetStr,
-                                  errorMessage);
+          String msg = getMessage(msgID, operationType);
 
           if(!modifyOptions.continueOnError())
           {
-            throw new LDAPException(resultCode, msgID, msg);
+            throw new LDAPException(resultCode, errorMessage, msgID, msg,
+                                    matchedDN, null);
           } else
           {
-            err.println(msg);
+            LDAPToolUtils.printErrorMessage(err, msg, resultCode, errorMessage,
+                                            matchedDN);
           }
         } else
         {
@@ -1099,7 +1102,8 @@
       {
         debugCaught(DebugLogLevel.ERROR, le);
       }
-      err.println(wrapText(le.getMessage(), MAX_LINE_WIDTH));
+      LDAPToolUtils.printErrorMessage(err, le.getMessage(), le.getResultCode(),
+                                      le.getErrorMessage(), le.getMatchedDN());
       int code = le.getResultCode();
       return code;
     } catch(LDAPConnectionException lce)
@@ -1108,8 +1112,11 @@
       {
         debugCaught(DebugLogLevel.ERROR, lce);
       }
-      err.println(wrapText(lce.getMessage(), MAX_LINE_WIDTH));
-      int code = lce.getErrorCode();
+      LDAPToolUtils.printErrorMessage(err, lce.getMessage(),
+                                      lce.getResultCode(),
+                                      lce.getErrorMessage(),
+                                      lce.getMatchedDN());
+      int code = lce.getResultCode();
       return code;
     } catch(Exception e)
     {
diff --git a/opends/src/server/org/opends/server/tools/LDAPPasswordModify.java b/opends/src/server/org/opends/server/tools/LDAPPasswordModify.java
index 6ee069a..3a668eb 100644
--- a/opends/src/server/org/opends/server/tools/LDAPPasswordModify.java
+++ b/opends/src/server/org/opends/server/tools/LDAPPasswordModify.java
@@ -592,7 +592,7 @@
       int    msgID   = MSGID_LDAPPWMOD_CANNOT_CONNECT;
       String message = getMessage(msgID, lce.getMessage());
       err.println(wrapText(message, MAX_LINE_WIDTH));
-      return lce.getErrorCode();
+      return lce.getResultCode();
     }
 
     ASN1Reader reader = connection.getASN1Reader();
diff --git a/opends/src/server/org/opends/server/tools/LDAPSearch.java b/opends/src/server/org/opends/server/tools/LDAPSearch.java
index e080026..c1e643b 100644
--- a/opends/src/server/org/opends/server/tools/LDAPSearch.java
+++ b/opends/src/server/org/opends/server/tools/LDAPSearch.java
@@ -181,6 +181,7 @@
           {
             int resultCode = 0;
             String errorMessage = null;
+            DN matchedDN = null;
             ASN1Element element = connection.getASN1Reader().readElement();
             LDAPMessage responseMessage =
                  LDAPMessage.decode(ASN1Sequence.decodeAsSequence(element));
@@ -297,6 +298,7 @@
                      responseMessage.getSearchResultDoneProtocolOp();
                 resultCode = searchOp.getResultCode();
                 errorMessage = searchOp.getErrorMessage();
+                matchedDN = searchOp.getMatchedDN();
 
                 break;
               default:
@@ -310,11 +312,9 @@
             if(resultCode != SUCCESS && resultCode != REFERRAL)
             {
               int msgID = MSGID_OPERATION_FAILED;
-              if(errorMessage == null)
-              {
-                errorMessage = "Result Code:" + resultCode;
-              }
-              throw new LDAPException(resultCode, msgID, errorMessage);
+              String msg = getMessage(msgID, "SEARCH");
+              throw new LDAPException(resultCode, errorMessage, msgID, msg,
+                                      matchedDN, null);
             }
             else if (errorMessage != null)
             {
@@ -1454,7 +1454,9 @@
       {
         debugCaught(DebugLogLevel.ERROR, le);
       }
-      err.println(wrapText(le.getMessage(), MAX_LINE_WIDTH));
+
+      LDAPToolUtils.printErrorMessage(err, le.getMessage(), le.getResultCode(),
+                                      le.getErrorMessage(), le.getMatchedDN());
       int code = le.getResultCode();
       return code;
     } catch(LDAPConnectionException lce)
@@ -1463,8 +1465,11 @@
       {
         debugCaught(DebugLogLevel.ERROR, lce);
       }
-      err.println(wrapText(lce.getMessage(), MAX_LINE_WIDTH));
-      int code = lce.getErrorCode();
+      LDAPToolUtils.printErrorMessage(err, lce.getMessage(),
+                                      lce.getResultCode(),
+                                      lce.getErrorMessage(),
+                                      lce.getMatchedDN());
+      int code = lce.getResultCode();
       return code;
     } catch(Exception e)
     {
diff --git a/opends/src/server/org/opends/server/tools/LDAPToolUtils.java b/opends/src/server/org/opends/server/tools/LDAPToolUtils.java
index c8725c6..81b8c43 100644
--- a/opends/src/server/org/opends/server/tools/LDAPToolUtils.java
+++ b/opends/src/server/org/opends/server/tools/LDAPToolUtils.java
@@ -33,7 +33,11 @@
 
 import org.opends.server.protocols.asn1.ASN1OctetString;
 import org.opends.server.protocols.ldap.LDAPControl;
+import org.opends.server.protocols.ldap.LDAPResultCode;
+import org.opends.server.types.DN;
 
+import static org.opends.server.messages.MessageHandler.*;
+import static org.opends.server.messages.ToolMessages.*;
 import static org.opends.server.util.ServerConstants.*;
 import static org.opends.server.util.StaticUtils.*;
 
@@ -223,5 +227,44 @@
       }
   }
 
+  /**
+   * Prints a multi-line error message with the provided information to the
+   * given print stream.
+   *
+   * @param  err           The print stream to use to write the error message.
+   * @param  explanation   The general explanation to provide to the user, or
+   *                       {@code null} if there is none.
+   * @param  resultCode    The result code returned from the server, or -1 if
+   *                       there is none.
+   * @param  errorMessage  The additional information / error message returned
+   *                       from the server, or {@code null} if there was none.
+   * @param  matchedDN     The matched DN returned from the server, or
+   *                       {@code null} if there was none.
+   */
+  public static void printErrorMessage(PrintStream err, String explanation,
+                                       int resultCode, String errorMessage,
+                                       DN matchedDN)
+  {
+    if ((explanation != null) && (explanation.length() > 0))
+    {
+      err.println(explanation);
+    }
+
+    if (resultCode >= 0)
+    {
+      err.println(getMessage(MSGID_TOOL_RESULT_CODE, resultCode,
+                             LDAPResultCode.toString(resultCode)));
+    }
+
+    if ((errorMessage != null) && (errorMessage.length() > 0))
+    {
+      err.println(getMessage(MSGID_TOOL_ERROR_MESSAGE, errorMessage));
+    }
+
+    if (matchedDN != null)
+    {
+      err.println(getMessage(MSGID_TOOL_MATCHED_DN, matchedDN.toString()));
+    }
+  }
 }
 

--
Gitblit v1.10.0