]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms.ui/src/org/argeo/cms/widgets/auth/CompositeCallbackHandler.java
Close forgotten session
[lgpl/argeo-commons.git] / org.argeo.cms.ui / src / org / argeo / cms / widgets / auth / CompositeCallbackHandler.java
1 package org.argeo.cms.widgets.auth;
2
3 import java.io.IOException;
4 import java.util.Arrays;
5
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;
10 import javax.security.auth.callback.TextOutputCallback;
11 import javax.security.auth.callback.UnsupportedCallbackException;
12
13 import org.eclipse.swt.SWT;
14 import org.eclipse.swt.events.KeyEvent;
15 import org.eclipse.swt.events.KeyListener;
16 import org.eclipse.swt.events.ModifyEvent;
17 import org.eclipse.swt.events.ModifyListener;
18 import org.eclipse.swt.events.SelectionEvent;
19 import org.eclipse.swt.events.SelectionListener;
20 import org.eclipse.swt.layout.GridData;
21 import org.eclipse.swt.widgets.Combo;
22 import org.eclipse.swt.widgets.Composite;
23 import org.eclipse.swt.widgets.Control;
24 import org.eclipse.swt.widgets.Label;
25 import org.eclipse.swt.widgets.Text;
26
27 /**
28 * A composite that can populate itself based on {@link Callback}s. It can be
29 * used directly as a {@link CallbackHandler} or be used by one by calling the
30 * {@link #createCallbackHandlers(Callback[])}.
31 * <p>
32 * Supported standard {@link Callback}s are:<br>
33 * <ul>
34 * <li>{@link PasswordCallback}</li>
35 * <li>{@link NameCallback}</li>
36 * <li>{@link TextOutputCallback}</li>
37 * </ul>
38 * </p>
39 * <p>
40 * Supported Argeo {@link Callback}s are:<br>
41 * <ul>
42 * <li>{@link LocaleChoice}</li>
43 * </ul>
44 * </p>
45 */
46 public class CompositeCallbackHandler extends Composite implements
47 CallbackHandler {
48 private static final long serialVersionUID = -928223893722723777L;
49
50 private boolean wasUsedAlready = false;
51 private boolean isSubmitted = false;
52 private boolean isCanceled = false;
53
54 public CompositeCallbackHandler(Composite parent, int style) {
55 super(parent, style);
56 }
57
58 @Override
59 public synchronized void handle(final Callback[] callbacks)
60 throws IOException, UnsupportedCallbackException {
61 // reset
62 if (wasUsedAlready && !isSubmitted() && !isCanceled()) {
63 cancel();
64 for (Control control : getChildren())
65 control.dispose();
66 isSubmitted = false;
67 isCanceled = false;
68 }
69
70 for (Callback callback : callbacks)
71 checkCallbackSupported(callback);
72 // create controls synchronously in the UI thread
73 getDisplay().syncExec(new Runnable() {
74
75 @Override
76 public void run() {
77 createCallbackHandlers(callbacks);
78 }
79 });
80
81 if (!wasUsedAlready)
82 wasUsedAlready = true;
83
84 // while (!isSubmitted() && !isCanceled()) {
85 // try {
86 // wait(1000l);
87 // } catch (InterruptedException e) {
88 // // silent
89 // }
90 // }
91
92 // cleanCallbacksAfterCancel(callbacks);
93 }
94
95 public void checkCallbackSupported(Callback callback)
96 throws UnsupportedCallbackException {
97 if (callback instanceof TextOutputCallback
98 || callback instanceof NameCallback
99 || callback instanceof PasswordCallback
100 || callback instanceof LocaleChoice) {
101 return;
102 } else {
103 throw new UnsupportedCallbackException(callback);
104 }
105 }
106
107 /**
108 * Set writable callbacks to null if the handle is canceled (check is done
109 * by the method)
110 */
111 public void cleanCallbacksAfterCancel(Callback[] callbacks) {
112 if (isCanceled()) {
113 for (Callback callback : callbacks) {
114 if (callback instanceof NameCallback) {
115 ((NameCallback) callback).setName(null);
116 } else if (callback instanceof PasswordCallback) {
117 PasswordCallback pCallback = (PasswordCallback) callback;
118 char[] arr = pCallback.getPassword();
119 if (arr != null) {
120 Arrays.fill(arr, '*');
121 pCallback.setPassword(null);
122 }
123 }
124 }
125 }
126 }
127
128 public void createCallbackHandlers(Callback[] callbacks) {
129 Composite composite = this;
130 for (int i = 0; i < callbacks.length; i++) {
131 Callback callback = callbacks[i];
132 if (callback instanceof TextOutputCallback) {
133 createLabelTextoutputHandler(composite,
134 (TextOutputCallback) callback);
135 } else if (callback instanceof NameCallback) {
136 createNameHandler(composite, (NameCallback) callback);
137 } else if (callback instanceof PasswordCallback) {
138 createPasswordHandler(composite, (PasswordCallback) callback);
139 } else if (callback instanceof LocaleChoice) {
140 createLocaleHandler(composite, (LocaleChoice) callback);
141 }
142 }
143 }
144
145 protected Text createNameHandler(Composite composite,
146 final NameCallback callback) {
147 Label label = new Label(composite, SWT.NONE);
148 label.setText(callback.getPrompt());
149 final Text text = new Text(composite, SWT.SINGLE | SWT.LEAD
150 | SWT.BORDER);
151 if (callback.getDefaultName() != null) {
152 // set default value, if provided
153 text.setText(callback.getDefaultName());
154 callback.setName(callback.getDefaultName());
155 }
156 text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
157 text.addModifyListener(new ModifyListener() {
158 private static final long serialVersionUID = 7300032545287292973L;
159
160 public void modifyText(ModifyEvent event) {
161 callback.setName(text.getText());
162 }
163 });
164 text.addSelectionListener(new SelectionListener() {
165 private static final long serialVersionUID = 1820530045857665111L;
166
167 @Override
168 public void widgetSelected(SelectionEvent e) {
169 }
170
171 @Override
172 public void widgetDefaultSelected(SelectionEvent e) {
173 submit();
174 }
175 });
176
177 text.addKeyListener(new KeyListener() {
178 private static final long serialVersionUID = -8698107785092095713L;
179
180 @Override
181 public void keyReleased(KeyEvent e) {
182 }
183
184 @Override
185 public void keyPressed(KeyEvent e) {
186 }
187 });
188 return text;
189 }
190
191 protected Text createPasswordHandler(Composite composite,
192 final PasswordCallback callback) {
193 Label label = new Label(composite, SWT.NONE);
194 label.setText(callback.getPrompt());
195 final Text passwordText = new Text(composite, SWT.SINGLE | SWT.LEAD
196 | SWT.PASSWORD | SWT.BORDER);
197 passwordText
198 .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
199 passwordText.addModifyListener(new ModifyListener() {
200 private static final long serialVersionUID = -7099363995047686732L;
201
202 public void modifyText(ModifyEvent event) {
203 callback.setPassword(passwordText.getTextChars());
204 }
205 });
206 passwordText.addSelectionListener(new SelectionListener() {
207 private static final long serialVersionUID = 1820530045857665111L;
208
209 @Override
210 public void widgetSelected(SelectionEvent e) {
211 }
212
213 @Override
214 public void widgetDefaultSelected(SelectionEvent e) {
215 submit();
216 }
217 });
218 return passwordText;
219 }
220
221 protected Combo createLocaleHandler(Composite composite,
222 final LocaleChoice callback) {
223 String[] labels = callback.getSupportedLocalesLabels();
224 if (labels.length == 0)
225 return null;
226 Label label = new Label(composite, SWT.NONE);
227 label.setText("Language");
228
229 final Combo combo = new Combo(composite, SWT.READ_ONLY);
230 combo.setItems(labels);
231 combo.select(callback.getDefaultIndex());
232 combo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
233 combo.addSelectionListener(new SelectionListener() {
234 private static final long serialVersionUID = 38678989091946277L;
235
236 @Override
237 public void widgetSelected(SelectionEvent e) {
238 callback.setSelectedIndex(combo.getSelectionIndex());
239 }
240
241 @Override
242 public void widgetDefaultSelected(SelectionEvent e) {
243 }
244 });
245 return combo;
246 }
247
248 protected Label createLabelTextoutputHandler(Composite composite,
249 final TextOutputCallback callback) {
250 Label label = new Label(composite, SWT.NONE);
251 label.setText(callback.getMessage());
252 GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
253 data.horizontalSpan = 2;
254 label.setLayoutData(data);
255 return label;
256 // TODO: find a way to pass this information
257 // int messageType = callback.getMessageType();
258 // int dialogMessageType = IMessageProvider.NONE;
259 // switch (messageType) {
260 // case TextOutputCallback.INFORMATION:
261 // dialogMessageType = IMessageProvider.INFORMATION;
262 // break;
263 // case TextOutputCallback.WARNING:
264 // dialogMessageType = IMessageProvider.WARNING;
265 // break;
266 // case TextOutputCallback.ERROR:
267 // dialogMessageType = IMessageProvider.ERROR;
268 // break;
269 // }
270 // setMessage(callback.getMessage(), dialogMessageType);
271 }
272
273 synchronized boolean isSubmitted() {
274 return isSubmitted;
275 }
276
277 synchronized boolean isCanceled() {
278 return isCanceled;
279 }
280
281 protected synchronized void submit() {
282 isSubmitted = true;
283 notifyAll();
284 }
285
286 protected synchronized void cancel() {
287 isCanceled = true;
288 notifyAll();
289 }
290 }