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