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