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() {
isCancelled = false;
setBlockOnOpen(false);
open();
+
final Button okButton = getButton(IDialogConstants.OK_ID);
okButton.setText("Login");
okButton.addSelectionListener(new SelectionListener() {
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;
+ log.debug("Thread " + Thread.currentThread().getId() + " died");
+ 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();
+ // } catch (InterruptedException ie) {
+ // // silent
+ // }
+ modalContextThread = null;
}
}
protected void configureShell(Shell shell) {
super.configureShell(shell);
- shell.setText("Login");
+ shell.setText("Authentication");
}
}