import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.security.ui.SecurityUiPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
+/** Base for login dialogs */
public abstract class AbstractLoginDialog extends TrayDialog implements
CallbackHandler {
+ private final static Log log = LogFactory.getLog(AbstractLoginDialog.class);
+
+ private Thread modalContextThread = null;
boolean processCallbacks = false;
boolean isCancelled = false;
Callback[] callbackArray;
* .callback.Callback[])
*/
public void handle(final Callback[] callbacks) throws IOException {
+ // clean previous usage
+ if (processCallbacks) {
+ // this handler was already used
+ processCallbacks = false;
+ }
+
+ if (modalContextThread != null) {
+ try {
+ modalContextThread.join(1000);
+ } catch (InterruptedException e) {
+ // silent
+ }
+ modalContextThread = null;
+ }
+
+ // initialize
this.callbackArray = callbacks;
final Display display = Display.getDefault();
display.syncExec(new Runnable() {
ModalContext.run(new IRunnableWithProgress() {
public void run(final IProgressMonitor monitor) {
+ modalContextThread = Thread.currentThread();
// Wait here until OK or cancel is pressed, then let it rip.
// The event
// listener
// is responsible for closing the dialog (in the
// loginSucceeded
// event).
- while (!processCallbacks) {
+ while (!processCallbacks && (modalContextThread != null)
+ && (modalContextThread == Thread.currentThread())
+ && SecurityUiPlugin.getDefault() != null) {
+ // Note: SecurityUiPlugin.getDefault() != null is false
+ // when the OSGi runtime is shut down
try {
Thread.sleep(100);
+ if (display.isDisposed()) {
+ log.warn("Display is disposed, killing login dialog thread");
+ throw new ThreadDeath();
+ }
} catch (final Exception e) {
// do nothing
}
((NameCallback) callback).setName(null);
}
}, true, new NullProgressMonitor(), Display.getDefault());
- } catch (final Exception e) {
- final IOException ioe = new IOException();
+ } catch (ThreadDeath e) {
+ isCancelled = true;
+ throw e;
+ } catch (Exception e) {
+ isCancelled = true;
+ IOException ioe = new IOException(
+ "Unexpected issue in login dialog, see root cause for more details");
ioe.initCause(e);
throw ioe;
+ } finally {
+ // so that the modal thread dies
+ processCallbacks = true;
+ try {
+ // wait for the modal context thread to gracefully exit
+ modalContextThread.join(1000);
+ } catch (InterruptedException ie) {
+ // silent
+ }
+ modalContextThread = null;
}
}