From 3259d2c6e62e37a9f6f7fb4afc82a0820f8848e1 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Fri, 21 Sep 2012 12:08:40 +0000
Subject: [PATCH] Fix OPENDJ-464: NPE in PasswordPolicyStateExtendedResult results in eternal waiting

---
 opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/GetConnectionIDExtendedRequest.java        |   38 ++++-----
 opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/PasswordPolicyStateExtendedResult.java     |   39 ++++-----
 opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/PasswordPolicyStateExtendedRequest.java    |   96 ++++++++++-------------
 opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/PasswordPolicyStateOperationContainer.java |   19 ++++
 opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/GetConnectionIDExtendedResult.java         |   15 +--
 5 files changed, 104 insertions(+), 103 deletions(-)

diff --git a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/GetConnectionIDExtendedRequest.java b/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/GetConnectionIDExtendedRequest.java
index 0f6d272..c66331c 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/GetConnectionIDExtendedRequest.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/GetConnectionIDExtendedRequest.java
@@ -80,7 +80,7 @@
                 throw new IllegalArgumentException("No response name and value for result code "
                         + resultCode.intValue());
             }
-            return GetConnectionIDExtendedResult.newResult(resultCode, -1).setMatchedDN(matchedDN)
+            return GetConnectionIDExtendedResult.newResult(resultCode).setMatchedDN(matchedDN)
                     .setDiagnosticMessage(diagnosticMessage);
         }
 
@@ -90,30 +90,28 @@
                 return (GetConnectionIDExtendedResult) result;
             } else {
                 final ResultCode resultCode = result.getResultCode();
-                final ByteString responseValue = result.getValue();
+                final GetConnectionIDExtendedResult newResult =
+                        GetConnectionIDExtendedResult.newResult(resultCode).setMatchedDN(
+                                result.getMatchedDN()).setDiagnosticMessage(
+                                result.getDiagnosticMessage());
 
-                if (!resultCode.isExceptional()
-                        && ((responseValue == null) || (responseValue.length() <= 0))) {
+                final ByteString responseValue = result.getValue();
+                if (!resultCode.isExceptional() && responseValue == null) {
                     throw DecodeException.error(LocalizableMessage.raw("Empty response value"));
                 }
-
-                try {
-                    final ASN1Reader reader = ASN1.getReader(responseValue);
-                    final int connectionID = (int) reader.readInteger();
-                    final GetConnectionIDExtendedResult newResult =
-                            GetConnectionIDExtendedResult.newResult(resultCode, connectionID)
-                                    .setMatchedDN(result.getMatchedDN()).setDiagnosticMessage(
-                                            result.getDiagnosticMessage());
-
-                    for (final Control control : result.getControls()) {
-                        newResult.addControl(control);
+                if (responseValue != null) {
+                    try {
+                        final ASN1Reader reader = ASN1.getReader(responseValue);
+                        newResult.setConnectionID((int) reader.readInteger());
+                    } catch (final IOException e) {
+                        throw DecodeException.error(LocalizableMessage
+                                .raw("Error decoding response value"), e);
                     }
-
-                    return newResult;
-                } catch (final IOException e) {
-                    throw DecodeException.error(LocalizableMessage
-                            .raw("Error decoding response value"), e);
                 }
+                for (final Control control : result.getControls()) {
+                    newResult.addControl(control);
+                }
+                return newResult;
             }
         }
     }
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/GetConnectionIDExtendedResult.java b/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/GetConnectionIDExtendedResult.java
index 25adf4c..30033b3 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/GetConnectionIDExtendedResult.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/GetConnectionIDExtendedResult.java
@@ -46,27 +46,24 @@
 public final class GetConnectionIDExtendedResult extends
         AbstractExtendedResult<GetConnectionIDExtendedResult> {
     /**
-     * Creates a new get connection ID extended result.
+     * Creates a new get connection ID extended result with a default connection
+     * ID of -1.
      *
      * @param resultCode
      *            The result code.
-     * @param connectionID
-     *            The client connection ID.
      * @return The new get connection ID extended result.
      * @throws NullPointerException
      *             If {@code resultCode} was {@code null}.
      */
-    public static GetConnectionIDExtendedResult newResult(final ResultCode resultCode,
-            final int connectionID) {
+    public static GetConnectionIDExtendedResult newResult(final ResultCode resultCode) {
         Validator.ensureNotNull(resultCode);
-        return new GetConnectionIDExtendedResult(resultCode, connectionID);
+        return new GetConnectionIDExtendedResult(resultCode);
     }
 
-    private int connectionID;
+    private int connectionID = -1;
 
-    private GetConnectionIDExtendedResult(final ResultCode resultCode, final int connectionID) {
+    private GetConnectionIDExtendedResult(final ResultCode resultCode) {
         super(resultCode);
-        this.connectionID = connectionID;
     }
 
     /**
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/PasswordPolicyStateExtendedRequest.java b/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/PasswordPolicyStateExtendedRequest.java
index ccfffbc..93166ca 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/PasswordPolicyStateExtendedRequest.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/PasswordPolicyStateExtendedRequest.java
@@ -45,7 +45,6 @@
 import org.forgerock.opendj.asn1.ASN1Writer;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ByteStringBuilder;
-import org.forgerock.opendj.ldap.DN;
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.DecodeOptions;
 import org.forgerock.opendj.ldap.ResultCode;
@@ -57,8 +56,6 @@
 import org.forgerock.opendj.ldap.responses.ExtendedResult;
 import org.forgerock.opendj.ldap.responses.ExtendedResultDecoder;
 
-import com.forgerock.opendj.util.Validator;
-
 /**
  * This class implements an LDAP extended operation that can be used to query
  * and update elements of the Directory Server password policy state for a given
@@ -170,18 +167,17 @@
                 final ExtendedRequest<?> request, final DecodeOptions options)
                 throws DecodeException {
             final ByteString requestValue = request.getValue();
-
             if ((requestValue == null) || (requestValue.length() <= 0)) {
                 throw DecodeException.error(ERR_PWPSTATE_EXTOP_NO_REQUEST_VALUE.get());
             }
-
             try {
                 final ASN1Reader reader = ASN1.getReader(requestValue);
                 reader.readStartSequence();
 
                 // Read the target user DN
                 final PasswordPolicyStateExtendedRequest newRequest =
-                        new PasswordPolicyStateExtendedRequest(reader.readOctetStringAsString());
+                        new PasswordPolicyStateExtendedRequest();
+                newRequest.setTargetUser(reader.readOctetStringAsString());
 
                 decodeOperations(reader, newRequest);
                 reader.readEndSequence();
@@ -214,43 +210,39 @@
                         + resultCode.intValue());
             }
 
-            return new PasswordPolicyStateExtendedResult(resultCode, (String) null).setMatchedDN(
+            return new PasswordPolicyStateExtendedResult(resultCode).setMatchedDN(
                     matchedDN).setDiagnosticMessage(diagnosticMessage);
         }
 
         public PasswordPolicyStateExtendedResult decodeExtendedResult(final ExtendedResult result,
                 final DecodeOptions options) throws DecodeException {
             final ResultCode resultCode = result.getResultCode();
-            final ByteString responseValue = result.getValue();
+            final PasswordPolicyStateExtendedResult newResult =
+                    new PasswordPolicyStateExtendedResult(resultCode).setMatchedDN(
+                            result.getMatchedDN()).setDiagnosticMessage(
+                            result.getDiagnosticMessage());
 
-            if (!resultCode.isExceptional()
-                    && ((responseValue == null) || (responseValue.length() <= 0))) {
+            final ByteString responseValue = result.getValue();
+            if (!resultCode.isExceptional() && responseValue == null) {
                 throw DecodeException.error(ERR_PWPSTATE_EXTOP_NO_REQUEST_VALUE.get());
             }
-
-            try {
-                final ASN1Reader reader = ASN1.getReader(responseValue);
-                reader.readStartSequence();
-
-                // Read the target user DN
-                final PasswordPolicyStateExtendedResult newResult =
-                        new PasswordPolicyStateExtendedResult(resultCode, reader
-                                .readOctetStringAsString()).setMatchedDN(result.getMatchedDN())
-                                .setDiagnosticMessage(result.getDiagnosticMessage());
-
-                decodeOperations(reader, newResult);
-                reader.readEndSequence();
-
-                for (final Control control : result.getControls()) {
-                    newResult.addControl(control);
+            if (responseValue != null) {
+                try {
+                    final ASN1Reader reader = ASN1.getReader(responseValue);
+                    reader.readStartSequence();
+                    newResult.setTargetUser(reader.readOctetStringAsString());
+                    decodeOperations(reader, newResult);
+                    reader.readEndSequence();
+                } catch (final IOException ioe) {
+                    final LocalizableMessage message =
+                            ERR_PWPSTATE_EXTOP_DECODE_FAILURE.get(getExceptionMessage(ioe));
+                    throw DecodeException.error(message, ioe);
                 }
-
-                return newResult;
-            } catch (final IOException ioe) {
-                final LocalizableMessage message =
-                        ERR_PWPSTATE_EXTOP_DECODE_FAILURE.get(getExceptionMessage(ioe));
-                throw DecodeException.error(message, ioe);
             }
+            for (final Control control : result.getControls()) {
+                newResult.addControl(control);
+            }
+            return newResult;
         }
     }
 
@@ -260,7 +252,7 @@
      */
     public static final String OID = "1.3.6.1.4.1.26027.1.6.1";
 
-    private final String targetUser;
+    private String targetUser = "";
 
     private final List<PasswordPolicyStateOperation> operations =
             new ArrayList<PasswordPolicyStateOperation>();
@@ -392,27 +384,10 @@
     }
 
     /**
-     * Creates a new password policy state extended request using the provided
-     * user name.
-     *
-     * @param targetUser
-     *            The name of the user.
+     * Creates a new password policy state extended request.
      */
-    public PasswordPolicyStateExtendedRequest(final DN targetUser) {
-        Validator.ensureNotNull(targetUser);
-        this.targetUser = targetUser.toString();
-    }
-
-    /**
-     * Creates a new password policy state extended request using the provided
-     * user name.
-     *
-     * @param targetUser
-     *            The name of the user.
-     */
-    public PasswordPolicyStateExtendedRequest(final String targetUser) {
-        Validator.ensureNotNull(targetUser);
-        this.targetUser = targetUser;
+    public PasswordPolicyStateExtendedRequest() {
+        // Nothing to do.
     }
 
     /**
@@ -550,6 +525,13 @@
     /**
      * {@inheritDoc}
      */
+    public String getTargetUser() {
+        return targetUser;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public ByteString getValue() {
         return encode(targetUser, operations);
@@ -849,6 +831,14 @@
      * {@inheritDoc}
      */
     @Override
+    public void setTargetUser(String targetUser) {
+        this.targetUser = targetUser != null ? targetUser : "";
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public String toString() {
         final StringBuilder builder = new StringBuilder();
         builder.append("PasswordPolicyStateExtendedRequest(requestName=");
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/PasswordPolicyStateExtendedResult.java b/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/PasswordPolicyStateExtendedResult.java
index eae5979..8bac7b6 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/PasswordPolicyStateExtendedResult.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/PasswordPolicyStateExtendedResult.java
@@ -30,7 +30,6 @@
 import java.util.List;
 
 import org.forgerock.opendj.ldap.ByteString;
-import org.forgerock.opendj.ldap.DN;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.responses.AbstractExtendedResult;
 
@@ -40,36 +39,19 @@
 public final class PasswordPolicyStateExtendedResult extends
         AbstractExtendedResult<PasswordPolicyStateExtendedResult> implements
         PasswordPolicyStateOperationContainer {
-    private final String targetUser;
-
+    private String targetUser = "";
     private final List<PasswordPolicyStateOperation> operations =
             new ArrayList<PasswordPolicyStateOperation>();
 
     /**
      * Creates a new password policy state extended result with the provided
-     * result code and target user.
+     * result code.
      *
      * @param resultCode
      *            The result code.
-     * @param targetUser
-     *            The user name.
      */
-    public PasswordPolicyStateExtendedResult(final ResultCode resultCode, final DN targetUser) {
-        this(resultCode, String.valueOf(targetUser));
-    }
-
-    /**
-     * Creates a new password policy state extended result with the provided
-     * result code and target user.
-     *
-     * @param resultCode
-     *            The result code.
-     * @param targetUser
-     *            The user name.
-     */
-    public PasswordPolicyStateExtendedResult(final ResultCode resultCode, final String targetUser) {
+    public PasswordPolicyStateExtendedResult(final ResultCode resultCode) {
         super(resultCode);
-        this.targetUser = targetUser;
     }
 
     /**
@@ -98,6 +80,13 @@
     /**
      * {@inheritDoc}
      */
+    public String getTargetUser() {
+        return targetUser;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public ByteString getValue() {
         return PasswordPolicyStateExtendedRequest.encode(targetUser, operations);
@@ -115,6 +104,14 @@
      * {@inheritDoc}
      */
     @Override
+    public void setTargetUser(String targetUser) {
+        this.targetUser = targetUser != null ? targetUser : "";
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public String toString() {
         final StringBuilder builder = new StringBuilder();
         builder.append("PasswordPolicyStateExtendedResponse(resultCode=");
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/PasswordPolicyStateOperationContainer.java b/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/PasswordPolicyStateOperationContainer.java
index cc295e1..c62b7ce 100644
--- a/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/PasswordPolicyStateOperationContainer.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/extensions/PasswordPolicyStateOperationContainer.java
@@ -31,6 +31,25 @@
  */
 interface PasswordPolicyStateOperationContainer {
     /**
+     * Returns the name of the user targeted by this password policy state
+     * operation.
+     *
+     * @return The name of the user targeted by this password policy state
+     *         operation.
+     */
+    String getTargetUser();
+
+    /**
+     * Sets the name of the user targeted by this password policy state
+     * operation.
+     *
+     * @param targetUser
+     *            The name of the user targeted by this password policy state
+     *            operation.
+     */
+    void setTargetUser(String targetUser);
+
+    /**
      * Adds an operation to this container.
      *
      * @param operation

--
Gitblit v1.10.0