]> git.argeo.org Git - lgpl/argeo-commons.git/blob - security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/AbstractLoginDialog.java
Logging management
[lgpl/argeo-commons.git] / security / plugins / org.argeo.security.ui / src / main / java / org / argeo / security / ui / dialogs / AbstractLoginDialog.java
1 package org.argeo.security.ui.dialogs;
2
3 import java.io.IOException;
4
5 import javax.security.auth.callback.Callback;
6 import javax.security.auth.callback.CallbackHandler;
7 import javax.security.auth.callback.NameCallback;
8 import javax.security.auth.callback.PasswordCallback;
9
10 import org.apache.commons.logging.Log;
11 import org.apache.commons.logging.LogFactory;
12 import org.argeo.security.ui.SecurityUiPlugin;
13 import org.eclipse.core.runtime.IProgressMonitor;
14 import org.eclipse.core.runtime.NullProgressMonitor;
15 import org.eclipse.jface.dialogs.IDialogConstants;
16 import org.eclipse.jface.dialogs.TrayDialog;
17 import org.eclipse.jface.operation.IRunnableWithProgress;
18 import org.eclipse.jface.operation.ModalContext;
19 import org.eclipse.swt.events.SelectionEvent;
20 import org.eclipse.swt.events.SelectionListener;
21 import org.eclipse.swt.widgets.Button;
22 import org.eclipse.swt.widgets.Display;
23 import org.eclipse.swt.widgets.Shell;
24
25 /** Base for login dialogs */
26 public abstract class AbstractLoginDialog extends TrayDialog implements
27 CallbackHandler {
28
29 private final static Log log = LogFactory.getLog(AbstractLoginDialog.class);
30
31 private Thread modalContextThread = null;
32 boolean processCallbacks = false;
33 boolean isCancelled = false;
34 Callback[] callbackArray;
35
36 protected final Callback[] getCallbacks() {
37 return this.callbackArray;
38 }
39
40 public abstract void internalHandle();
41
42 public boolean isCancelled() {
43 return isCancelled;
44 }
45
46 protected AbstractLoginDialog(Shell parentShell) {
47 super(parentShell);
48 }
49
50 /*
51 * (non-Javadoc)
52 *
53 * @see
54 * javax.security.auth.callback.CallbackHandler#handle(javax.security.auth
55 * .callback.Callback[])
56 */
57 public void handle(final Callback[] callbacks) throws IOException {
58 // clean previous usage
59 if (processCallbacks) {
60 // this handler was already used
61 processCallbacks = false;
62 }
63
64 if (modalContextThread != null) {
65 try {
66 modalContextThread.join(1000);
67 } catch (InterruptedException e) {
68 // silent
69 }
70 modalContextThread = null;
71 }
72
73 // initialize
74 this.callbackArray = callbacks;
75 final Display display = Display.getDefault();
76 display.syncExec(new Runnable() {
77
78 public void run() {
79 isCancelled = false;
80 setBlockOnOpen(false);
81 open();
82
83 final Button okButton = getButton(IDialogConstants.OK_ID);
84 okButton.setText("Login");
85 okButton.addSelectionListener(new SelectionListener() {
86
87 public void widgetSelected(final SelectionEvent event) {
88 processCallbacks = true;
89 }
90
91 public void widgetDefaultSelected(final SelectionEvent event) {
92 // nothing to do
93 }
94 });
95 final Button cancel = getButton(IDialogConstants.CANCEL_ID);
96 cancel.addSelectionListener(new SelectionListener() {
97
98 public void widgetSelected(final SelectionEvent event) {
99 isCancelled = true;
100 processCallbacks = true;
101 }
102
103 public void widgetDefaultSelected(final SelectionEvent event) {
104 // nothing to do
105 }
106 });
107 }
108 });
109 try {
110 ModalContext.setAllowReadAndDispatch(true); // Works for now.
111 ModalContext.run(new IRunnableWithProgress() {
112
113 public void run(final IProgressMonitor monitor) {
114 modalContextThread = Thread.currentThread();
115 // Wait here until OK or cancel is pressed, then let it rip.
116 // The event
117 // listener
118 // is responsible for closing the dialog (in the
119 // loginSucceeded
120 // event).
121 while (!processCallbacks && (modalContextThread != null)
122 && (modalContextThread == Thread.currentThread())
123 && SecurityUiPlugin.getDefault() != null) {
124 // Note: SecurityUiPlugin.getDefault() != null is false
125 // when the OSGi runtime is shut down
126 try {
127 Thread.sleep(100);
128 // if (display.isDisposed()) {
129 // log.warn("Display is disposed, killing login dialog thread");
130 // throw new ThreadDeath();
131 // }
132 } catch (final Exception e) {
133 // do nothing
134 }
135 }
136 processCallbacks = false;
137 // Call the adapter to handle the callbacks
138 if (!isCancelled())
139 internalHandle();
140 else
141 // clear callbacks are when cancelling
142 for (Callback callback : callbacks)
143 if (callback instanceof PasswordCallback)
144 ((PasswordCallback) callback).setPassword(null);
145 else if (callback instanceof NameCallback)
146 ((NameCallback) callback).setName(null);
147 }
148 }, true, new NullProgressMonitor(), Display.getDefault());
149 } catch (ThreadDeath e) {
150 isCancelled = true;
151 log.debug("Thread " + Thread.currentThread().getId() + " died");
152 throw e;
153 } catch (Exception e) {
154 isCancelled = true;
155 IOException ioe = new IOException(
156 "Unexpected issue in login dialog, see root cause for more details");
157 ioe.initCause(e);
158 throw ioe;
159 } finally {
160 // so that the modal thread dies
161 processCallbacks = true;
162 // try {
163 // // wait for the modal context thread to gracefully exit
164 // modalContextThread.join();
165 // } catch (InterruptedException ie) {
166 // // silent
167 // }
168 modalContextThread = null;
169 }
170 }
171
172 protected void configureShell(Shell shell) {
173 super.configureShell(shell);
174 shell.setText("Authentication");
175 }
176 }