From 08db26a180ec0958cbc04ef4aa33debcacb3d5ed Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Thu, 22 Oct 2009 13:31:32 +0000
Subject: [PATCH] Control Panel fix for issue 4302 (Unexpected errors using single JNDI connection with SSL and multiple threads.)
---
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseEntriesPanel.java | 98 ++++++++++++++++++-----
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/util/LDAPEntryReader.java | 26 ++++++
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ControlPanelInfo.java | 115 +++++++++++++++-------------
3 files changed, 162 insertions(+), 77 deletions(-)
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ControlPanelInfo.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ControlPanelInfo.java
index af2c227..c1cb3c8 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ControlPanelInfo.java
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ControlPanelInfo.java
@@ -605,70 +605,48 @@
{
reader = createNewConfigFromDirContextReader();
((ConfigFromDirContext)reader).readConfiguration(ctx);
- if (reader.getExceptions().size() > 0)
+
+ boolean connectionWorks = checkConnections(ctx, userDataCtx);
+ if (!connectionWorks)
{
- // Check the connection
- boolean connectionWorks = false;
- int nMaxErrors = 5;
- for (int i=0; i< nMaxErrors && !connectionWorks; i++)
+ if (isLocal)
{
- try
- {
- Utilities.pingDirContext(ctx);
- connectionWorks = true;
- }
- catch (NamingException ne)
- {
- try
- {
- Thread.sleep(400);
- }
- catch (Throwable t)
- {
- }
- }
+ // Try with off-line info
+ reader = createNewConfigFromFileReader();
+ ((ConfigFromFile)reader).readConfiguration();
}
- if (!connectionWorks)
+ else
{
- if (isLocal)
- {
- // Try with offline info
- reader = createNewConfigFromFileReader();
- ((ConfigFromFile)reader).readConfiguration();
- }
- else
- {
- desc.setStatus(
- ServerDescriptor.ServerStatus.NOT_CONNECTED_TO_REMOTE);
- reader = null;
- }
+ desc.setStatus(
+ ServerDescriptor.ServerStatus.NOT_CONNECTED_TO_REMOTE);
+ reader = null;
+ }
+ try
+ {
+ ctx.close();
+ }
+ catch (Throwable t)
+ {
+ }
+ this.ctx = null;
+ if (connectionPool.isConnectionRegistered(userDataCtx))
+ {
try
{
- ctx.close();
+ connectionPool.unregisterConnection(userDataCtx);
}
catch (Throwable t)
{
}
- this.ctx = null;
- if (connectionPool.isConnectionRegistered(userDataCtx))
- {
- try
- {
- connectionPool.unregisterConnection(userDataCtx);
- }
- catch (Throwable t)
- {
- }
- }
- try
- {
- userDataCtx.close();
- }
- catch (Throwable t)
- {
- }
- userDataCtx = null;
}
+ try
+ {
+ userDataCtx.close();
+ }
+ catch (Throwable t)
+ {
+ }
+ userDataCtx = null;
}
}
}
@@ -1341,4 +1319,35 @@
}
return isRunningOnServer;
}
+
+ private boolean checkConnections(InitialLdapContext ctx,
+ InitialLdapContext userCtx)
+ {
+ // Check the connection
+ boolean connectionWorks = false;
+ int nMaxErrors = 5;
+ for (int i=0; i< nMaxErrors && !connectionWorks; i++)
+ {
+ try
+ {
+ Utilities.pingDirContext(ctx);
+ if (userCtx != null)
+ {
+ Utilities.pingDirContext(userCtx);
+ }
+ connectionWorks = true;
+ }
+ catch (NamingException ne)
+ {
+ try
+ {
+ Thread.sleep(400);
+ }
+ catch (Throwable t)
+ {
+ }
+ }
+ }
+ return connectionWorks;
+ }
}
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseEntriesPanel.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseEntriesPanel.java
index ff8ec76..9277f3e 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseEntriesPanel.java
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/BrowseEntriesPanel.java
@@ -67,11 +67,13 @@
import javax.swing.JSeparator;
import javax.swing.JSplitPane;
import javax.swing.JTree;
+import javax.swing.SwingUtilities;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreePath;
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
+import org.opends.guitools.controlpanel.datamodel.CustomSearchResult;
import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
import org.opends.guitools.controlpanel.event.EntryReadErrorEvent;
@@ -149,8 +151,9 @@
private boolean ignoreTreeSelectionEvents = false;
- private ArrayList<LDAPEntryReader> entryReaderQueue =
- new ArrayList<LDAPEntryReader>();
+ private LDAPEntryReader entryReader;
+
+ private Thread entryReaderThread;
/**
* {@inheritDoc}
@@ -523,12 +526,11 @@
controller.findConnectionForDisplayedEntry(node);
LDAPEntryReader reader = new LDAPEntryReader(dn, ctx);
reader.addEntryReadListener(entryPane);
- cleanupReaderQueue();
// Required to update the browser controller properly if the entry is
// deleted.
entryPane.setTreePath(path);
- reader.startBackgroundTask();
- entryReaderQueue.add(reader);
+ stopCurrentReader();
+ startReader(reader);
}
catch (Throwable t)
{
@@ -541,7 +543,7 @@
}
else
{
- cleanupReaderQueue();
+ stopCurrentReader();
if ((paths != null) && (paths.length > 1))
{
entryPane.multipleEntriesSelected();
@@ -553,26 +555,76 @@
}
}
- /**
- * Cleans up the reader queue (the queue where we store the entries that we
- * must read).
- *
- */
- private void cleanupReaderQueue()
+ private void stopCurrentReader()
{
- ArrayList<LDAPEntryReader> toRemove = new ArrayList<LDAPEntryReader>();
- for (LDAPEntryReader r : entryReaderQueue)
+ if (entryReader != null)
{
- if (r.isOver())
- {
- toRemove.add(r);
- }
- else
- {
- r.interrupt();
- }
+ entryReader.setNotifyListeners(false);
}
- entryReaderQueue.removeAll(toRemove);
+ }
+
+ /**
+ * Starts the provider reader.
+ * @param reader the LDAPEntryReader.
+ */
+ private void startReader(LDAPEntryReader reader)
+ {
+ entryReader = reader;
+ if ((entryReaderThread == null) || !entryReaderThread.isAlive())
+ {
+ entryReaderThread = new Thread(new Runnable()
+ {
+ LDAPEntryReader reader;
+ CustomSearchResult sr;
+ Throwable t;
+ public void run()
+ {
+ while (true)
+ {
+ try
+ {
+ synchronized (entryReaderThread)
+ {
+ while ((reader = entryReader) == null)
+ {
+ entryReaderThread.wait();
+ }
+ }
+ sr = null;
+ t = null;
+ try
+ {
+ sr = reader.processBackgroundTask();
+ }
+ catch (Throwable th)
+ {
+ t = th;
+ }
+ SwingUtilities.invokeAndWait(new Runnable()
+ {
+ public void run()
+ {
+ reader.backgroundTaskCompleted(sr, t);
+ if (reader == entryReader)
+ {
+ entryReader = null;
+ }
+ }
+ });
+ }
+ catch (Throwable t)
+ {
+ entryReader = null;
+ }
+ }
+ }
+ });
+ entryReaderThread.start();
+ }
+ synchronized (entryReaderThread)
+ {
+ entryReaderThread.notify();
+ }
}
/**
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/util/LDAPEntryReader.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/util/LDAPEntryReader.java
index 6e8ffc8..db80d86 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/util/LDAPEntryReader.java
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/util/LDAPEntryReader.java
@@ -52,6 +52,7 @@
private InitialLdapContext ctx;
private Set<EntryReadListener> listeners = new HashSet<EntryReadListener>();
private boolean isOver;
+ private boolean notifyListeners;
/**
* Constructor of the entry reader.
@@ -62,6 +63,7 @@
{
this.dn = dn;
this.ctx = ctx;
+ this.notifyListeners = true;
}
/**
@@ -102,7 +104,7 @@
public void backgroundTaskCompleted(CustomSearchResult sr,
Throwable throwable)
{
- if (!isInterrupted())
+ if (!isInterrupted() && isNotifyListeners())
{
if (throwable == null)
{
@@ -117,6 +119,28 @@
}
/**
+ * Returns whether this entry reader will notify the listeners once it is
+ * over.
+ * @return whether this entry reader will notify the listeners once it is
+ * over.
+ */
+ public boolean isNotifyListeners()
+ {
+ return notifyListeners;
+ }
+
+ /**
+ * Sets whether this entry reader will notify the listeners once it is
+ * over.
+ * @param notifyListeners whether this entry reader will notify the listeners
+ * once it is over.
+ */
+ public void setNotifyListeners(boolean notifyListeners)
+ {
+ this.notifyListeners = notifyListeners;
+ }
+
+ /**
* Returns <CODE>true</CODE> if the read process is over and
* <CODE>false</CODE> otherwise.
* @return <CODE>true</CODE> if the read process is over and
--
Gitblit v1.10.0