src/java.naming/share/classes/com/sun/jndi/ldap/LdapClient.java

Print this page

        

@@ -492,21 +492,19 @@
      * This is almost like forceClose(), except it doesn't call
      * Connection.cleanup() (because this is called from cleanup()).
      */
     void processConnectionClosure() {
         // Notify listeners
-        synchronized (unsolicited) {
             if (unsolicited.size() > 0) {
                 String msg;
                 if (conn != null) {
                     msg = conn.host + ":" + conn.port + " connection closed";
                 } else {
                     msg = "Connection closed";
                 }
                 notifyUnsolicited(new CommunicationException(msg));
             }
-        }
 
         // Remove from pool
         if (pooled) {
             pcb.removePooledConnection(this);
         }

@@ -1497,25 +1495,19 @@
 
     void removeUnsolicited(LdapCtx ctx) {
         if (debug > 0) {
             System.err.println("LdapClient.removeUnsolicited" + ctx);
         }
-        synchronized (unsolicited) {
-            if (unsolicited.size() == 0) {
-                return;
-            }
             unsolicited.removeElement(ctx);
         }
-    }
 
     // NOTE: Cannot be synchronized because this is called asynchronously
     // by the reader thread in Connection. Instead, sync on 'unsolicited' Vector.
     void processUnsolicited(BerDecoder ber) {
         if (debug > 0) {
             System.err.println("LdapClient.processUnsolicited");
         }
-        synchronized (unsolicited) {
             try {
                 // Parse the response
                 LdapResult res = new LdapResult();
 
                 ber.parseSeq(null); // init seq

@@ -1530,25 +1522,34 @@
                 if (DISCONNECT_OID.equals(res.extensionId)) {
                     // force closing of connection
                     forceClose(pooled);
                 }
 
+            LdapCtx first = null;
+            UnsolicitedNotification notice = null;
+
+            synchronized (unsolicited) {
                 if (unsolicited.size() > 0) {
+                    first = unsolicited.elementAt(0);
+
                     // Create an UnsolicitedNotification using the parsed data
                     // Need a 'ctx' object because we want to use the context's
                     // list of provider control factories.
-                    UnsolicitedNotification notice = new UnsolicitedResponseImpl(
+                    notice = new UnsolicitedResponseImpl(
                         res.extensionId,
                         res.extensionValue,
                         res.referrals,
                         res.status,
                         res.errorMessage,
                         res.matchedDN,
                         (res.resControls != null) ?
-                        unsolicited.elementAt(0).convertControls(res.resControls) :
+                        first.convertControls(res.resControls) :
                         null);
+                }
+            }
 
+            if (notice != null) {
                     // Fire UnsolicitedNotification events to listeners
                     notifyUnsolicited(notice);
 
                     // If "disconnect" notification,
                     // notify unsolicited listeners via NamingException

@@ -1556,13 +1557,10 @@
                         notifyUnsolicited(
                             new CommunicationException("Connection closed"));
                     }
                 }
             } catch (IOException e) {
-                if (unsolicited.size() == 0)
-                    return;  // no one registered; ignore
-
                 NamingException ne = new CommunicationException(
                     "Problem parsing unsolicited notification");
                 ne.setRootCause(e);
 
                 notifyUnsolicited(ne);

@@ -1569,21 +1567,24 @@
 
             } catch (NamingException e) {
                 notifyUnsolicited(e);
             }
         }
-    }
 
 
     private void notifyUnsolicited(Object e) {
-        for (int i = 0; i < unsolicited.size(); i++) {
-            unsolicited.elementAt(i).fireUnsolicited(e);
-        }
+        Vector<LdapCtx> unsolicitedCopy;
+        synchronized (unsolicited) {
+            unsolicitedCopy = new Vector<>(unsolicited);
         if (e instanceof NamingException) {
             unsolicited.setSize(0);  // no more listeners after exception
         }
     }
+        for (int i = 0; i < unsolicitedCopy.size(); i++) {
+            unsolicitedCopy.elementAt(i).fireUnsolicited(e);
+        }
+    }
 
     private void ensureOpen() throws IOException {
         if (conn == null || !conn.useable) {
             if (conn != null && conn.closureReason != null) {
                 throw conn.closureReason;