1 package org
.argeo
.cms
.ui
.workbench
;
3 import java
.io
.IOException
;
4 import java
.util
.Arrays
;
6 import javax
.security
.auth
.callback
.Callback
;
7 import javax
.security
.auth
.callback
.CallbackHandler
;
8 import javax
.security
.auth
.callback
.NameCallback
;
9 import javax
.security
.auth
.callback
.PasswordCallback
;
11 import org
.argeo
.api
.cms
.CmsLog
;
12 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
13 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
14 import org
.eclipse
.jface
.dialogs
.IDialogConstants
;
15 import org
.eclipse
.jface
.dialogs
.TrayDialog
;
16 import org
.eclipse
.jface
.operation
.IRunnableWithProgress
;
17 import org
.eclipse
.jface
.operation
.ModalContext
;
18 import org
.eclipse
.swt
.events
.SelectionEvent
;
19 import org
.eclipse
.swt
.events
.SelectionListener
;
20 import org
.eclipse
.swt
.widgets
.Button
;
21 import org
.eclipse
.swt
.widgets
.Display
;
22 import org
.eclipse
.swt
.widgets
.Shell
;
23 import org
.osgi
.framework
.FrameworkUtil
;
25 /** Base for login dialogs */
27 public abstract class AbstractLoginDialog
extends TrayDialog
implements CallbackHandler
{
28 private static final long serialVersionUID
= -8046708963512717709L;
30 private final static CmsLog log
= CmsLog
.getLog(AbstractLoginDialog
.class);
32 private Thread modalContextThread
= null;
33 boolean processCallbacks
= false;
34 boolean isCancelled
= false;
35 Callback
[] callbackArray
;
37 protected final Callback
[] getCallbacks() {
38 return this.callbackArray
;
41 public abstract void internalHandle();
43 public boolean isCancelled() {
47 protected AbstractLoginDialog(Shell parentShell
) {
55 * javax.security.auth.callback.CallbackHandler#handle(javax.security.auth
56 * .callback.Callback[])
58 public void handle(final Callback
[] callbacks
) throws IOException
{
59 // clean previous usage
60 if (processCallbacks
) {
61 // this handler was already used
62 processCallbacks
= false;
65 if (modalContextThread
!= null) {
67 modalContextThread
.join(1000);
68 } catch (InterruptedException e
) {
71 modalContextThread
= null;
75 this.callbackArray
= callbacks
;
76 final Display display
= Display
.getDefault();
77 display
.syncExec(new Runnable() {
81 setBlockOnOpen(false);
84 final Button okButton
= getButton(IDialogConstants
.OK_ID
);
85 okButton
.setText("Login");
86 okButton
.addSelectionListener(new SelectionListener() {
87 private static final long serialVersionUID
= -200281625679096775L;
89 public void widgetSelected(final SelectionEvent event
) {
90 processCallbacks
= true;
93 public void widgetDefaultSelected(final SelectionEvent event
) {
97 final Button cancel
= getButton(IDialogConstants
.CANCEL_ID
);
98 cancel
.addSelectionListener(new SelectionListener() {
99 private static final long serialVersionUID
= -3826030278084915815L;
101 public void widgetSelected(final SelectionEvent event
) {
103 processCallbacks
= true;
106 public void widgetDefaultSelected(final SelectionEvent event
) {
113 ModalContext
.setAllowReadAndDispatch(true); // Works for now.
114 ModalContext
.run(new IRunnableWithProgress() {
116 public void run(final IProgressMonitor monitor
) {
117 modalContextThread
= Thread
.currentThread();
118 // Wait here until OK or cancel is pressed, then let it rip.
121 // is responsible for closing the dialog (in the
124 while (!processCallbacks
&& (modalContextThread
!= null)
125 && (modalContextThread
== Thread
.currentThread())
126 && FrameworkUtil
.getBundle(AbstractLoginDialog
.class).getBundleContext() != null) {
127 // Note: SecurityUiPlugin.getDefault() != null is false
128 // when the OSGi runtime is shut down
131 // if (display.isDisposed()) {
132 // log.warn("Display is disposed, killing login
134 // throw new ThreadDeath();
136 } catch (final Exception e
) {
140 processCallbacks
= false;
141 // Call the adapter to handle the callbacks
145 // clear callbacks are when cancelling
146 for (Callback callback
: callbacks
)
147 if (callback
instanceof PasswordCallback
) {
148 char[] arr
= ((PasswordCallback
) callback
).getPassword();
150 Arrays
.fill(arr
, '*');
151 ((PasswordCallback
) callback
).setPassword(null);
153 } else if (callback
instanceof NameCallback
)
154 ((NameCallback
) callback
).setName(null);
156 }, true, new NullProgressMonitor(), Display
.getDefault());
157 } catch (ThreadDeath e
) {
159 log
.debug("Thread " + Thread
.currentThread().getId() + " died");
161 } catch (Exception e
) {
163 IOException ioe
= new IOException("Unexpected issue in login dialog, see root cause for more details");
167 // so that the modal thread dies
168 processCallbacks
= true;
170 // // wait for the modal context thread to gracefully exit
171 // modalContextThread.join();
172 // } catch (InterruptedException ie) {
175 modalContextThread
= null;
179 protected void configureShell(Shell shell
) {
180 super.configureShell(shell
);
181 shell
.setText("Authentication");