1 package ch.odi.justblog.gui.swing;
2
3 import java.awt.Component;
4 import java.awt.Container;
5 import java.awt.Frame;
6 import java.awt.GridBagConstraints;
7 import java.awt.GridBagLayout;
8 import java.awt.Insets;
9 import java.awt.event.ActionEvent;
10 import java.awt.event.ActionListener;
11 import java.io.IOException;
12 import java.util.ArrayList;
13 import java.util.Locale;
14
15 import javax.security.auth.callback.Callback;
16 import javax.security.auth.callback.ChoiceCallback;
17 import javax.security.auth.callback.ConfirmationCallback;
18 import javax.security.auth.callback.LanguageCallback;
19 import javax.security.auth.callback.NameCallback;
20 import javax.security.auth.callback.PasswordCallback;
21 import javax.security.auth.callback.TextInputCallback;
22 import javax.security.auth.callback.TextOutputCallback;
23 import javax.security.auth.callback.UnsupportedCallbackException;
24 import javax.swing.BoxLayout;
25 import javax.swing.ButtonGroup;
26 import javax.swing.JButton;
27 import javax.swing.JCheckBox;
28 import javax.swing.JComponent;
29 import javax.swing.JDialog;
30 import javax.swing.JLabel;
31 import javax.swing.JPanel;
32 import javax.swing.JPasswordField;
33 import javax.swing.JRadioButton;
34 import javax.swing.JTextField;
35 import javax.swing.JToggleButton;
36
37 import ch.odi.justblog.gui.IAuthenticator;
38
39 /***
40 * Creates a Swing GUI for authentication.
41 * @author oglueck
42 */
43 public class DialogAuthenticator implements IAuthenticator {
44 Frame owner;
45 String title;
46
47 /***
48 *
49 */
50 public DialogAuthenticator(Frame owner) {
51 this.owner = owner;
52 }
53
54 /***
55 * Sets the text to use as the dialog title.
56 * @param context the dialog title or <code>null</code>.
57 */
58 public void setContext(String context) {
59 this.title = context;
60 }
61
62 /***
63 * Creates a dialog out of the callbacks and pushes the information
64 * entered by the user back into the callbacks.
65 */
66 public void handle(Callback[] callbacks) throws IOException,
67 UnsupportedCallbackException {
68 final JDialog dlg = new JDialog(owner, true);
69 dlg.setTitle("Authenticate");
70 final Container cp = dlg.getContentPane();
71 GridBagLayout lo = new GridBagLayout();
72 GridBagConstraints cs = new GridBagConstraints();
73 cs.insets = new Insets(5,5,5, 5);
74 cs.gridwidth = GridBagConstraints.REMAINDER;
75 cs.anchor = GridBagConstraints.NORTHWEST;
76 cp.setLayout(lo);
77 JLabel lbl = new JLabel(title);
78 cp.add(lbl);
79 lo.setConstraints(lbl, cs);
80
81 boolean displayable = false;
82 for (int i=0; i<callbacks.length; i++) {
83 Callback cb = callbacks[i];
84 if (cb instanceof LanguageCallback) {
85 LanguageCallback lc = (LanguageCallback) cb;
86 lc.setLocale(Locale.getDefault());
87 } else if (cb instanceof NameCallback) {
88 JLabel label = new JLabel(((NameCallback) cb).getPrompt());
89 cp.add(label);
90 cs.gridwidth = 1;
91 lo.setConstraints(label, cs);
92 JComponent panel = new NameControl((NameCallback) cb);
93 cp.add(panel);
94 cs.gridwidth = GridBagConstraints.REMAINDER;
95 lo.setConstraints(panel, cs);
96 displayable = true;
97 } else if (cb instanceof PasswordCallback) {
98 JLabel label = new JLabel(((PasswordCallback) cb).getPrompt());
99 cp.add(label);
100 cs.gridwidth = 1;
101 lo.setConstraints(label, cs);
102 JComponent panel = new PasswordControl((PasswordCallback) cb);
103 cp.add(panel);
104 cs.gridwidth = GridBagConstraints.REMAINDER;
105 lo.setConstraints(panel, cs);
106 displayable = true;
107 } else if (cb instanceof TextOutputCallback) {
108 String label;
109 switch (((TextOutputCallback) cb).getMessageType()) {
110 case TextOutputCallback.ERROR:
111 label = "Error";
112 break;
113
114 case TextOutputCallback.WARNING:
115 label = "Warning";
116 break;
117
118 case TextOutputCallback.INFORMATION:
119 label = "Information";
120 break;
121
122 default:
123 label = "";
124 }
125 JLabel jlabel = new JLabel(label);
126 cp.add(jlabel);
127 cs.gridwidth = 1;
128 lo.setConstraints(jlabel, cs);
129 JComponent panel = new JLabel(((TextOutputCallback) cb).getMessage());
130 cp.add(panel);
131 cs.gridwidth = GridBagConstraints.REMAINDER;
132 lo.setConstraints(panel, cs);
133 displayable = true;
134 } else if (cb instanceof TextInputCallback) {
135 JLabel label = new JLabel(((TextInputCallback) cb).getPrompt());
136 cp.add(label);
137 cs.gridwidth = 1;
138 lo.setConstraints(label, cs);
139 JComponent panel = new TextInputControl((TextInputCallback) cb);
140 cp.add(panel);
141 cs.gridwidth = GridBagConstraints.REMAINDER;
142 lo.setConstraints(panel, cs);
143 displayable = true;
144 } else if (cb instanceof ChoiceCallback) {
145 JLabel label = new JLabel(((ChoiceCallback) cb).getPrompt());
146 cp.add(label);
147 cs.gridwidth = 1;
148 lo.setConstraints(label, cs);
149 JComponent panel = new ChoiceControl((ChoiceCallback) cb);
150 cp.add(panel);
151 cs.gridwidth = GridBagConstraints.REMAINDER;
152 lo.setConstraints(panel, cs);
153 displayable = true;
154 } else if (cb instanceof ConfirmationCallback) {
155 String prompt;
156 switch (((ConfirmationCallback) cb).getMessageType()) {
157 case ConfirmationCallback.ERROR:
158 prompt = "Error";
159 break;
160
161 case ConfirmationCallback.WARNING:
162 prompt = "Warning";
163 break;
164
165 case ConfirmationCallback.INFORMATION:
166 prompt = "Information";
167 break;
168
169 default:
170 prompt = "";
171 }
172 if (((ConfirmationCallback) cb).getPrompt() != null) {
173 prompt += ": "+ ((ConfirmationCallback) cb).getPrompt();
174 }
175 JLabel label = new JLabel(prompt);
176 cp.add(label);
177 cs.gridwidth = 1;
178 lo.setConstraints(label, cs);
179 JComponent panel = new ConfirmationControl((ConfirmationCallback) cb);
180 cp.add(panel);
181 cs.gridwidth = GridBagConstraints.REMAINDER;
182 lo.setConstraints(panel, cs);
183 displayable = true;
184 } else throw new UnsupportedCallbackException(cb);
185
186 }
187 if (!displayable) {
188 dlg.dispose();
189 return;
190 }
191 JButton ok = new JButton("Ok");
192 ok.setActionCommand("ok");
193 ok.addActionListener(
194 new ActionListener() {
195 public void actionPerformed(ActionEvent e) {
196 try {
197 Component[] components = cp.getComponents();
198 for (int i = 0; i < components.length; i++) {
199 if (! (components[i] instanceof Commitable)) continue;
200 ((Commitable) components[i]).commit();
201 }
202 } finally {
203 dlg.dispose();
204 }
205 }
206 }
207 );
208 ok.setDefaultCapable(true);
209 cp.add(ok);
210 cs.anchor = GridBagConstraints.NORTHEAST;
211 lo.setConstraints(ok, cs);
212 dlg.getRootPane().setDefaultButton(ok);
213 dlg.pack();
214 dlg.setResizable(false);
215 dlg.show();
216 }
217
218 interface Commitable {
219 void commit();
220 }
221
222 class NameControl extends JTextField implements Commitable {
223 private NameCallback cb;
224
225 public NameControl(NameCallback cb) {
226 super(10);
227 this.cb = cb;
228 }
229
230 public void commit() {
231 cb.setName(this.getText());
232 }
233 }
234
235 class TextInputControl extends JTextField implements Commitable {
236 private TextInputCallback cb;
237
238 public TextInputControl(TextInputCallback cb) {
239 super(10);
240 this.cb = cb;
241 this.setText(cb.getDefaultText());
242 }
243
244 public void commit() {
245 cb.setText(this.getText());
246 }
247 }
248
249 class PasswordControl extends JPasswordField implements Commitable {
250 private PasswordCallback cb;
251
252 public PasswordControl(PasswordCallback cb) {
253 super(10);
254 this.cb = cb;
255 }
256
257 public void commit() {
258 cb.setPassword(this.getPassword());
259 }
260 }
261
262 class ChoiceControl extends JPanel implements Commitable {
263 private ChoiceCallback cb;
264
265 public ChoiceControl(ChoiceCallback cb) {
266 this.cb = cb;
267 BoxLayout lo = new BoxLayout(this, BoxLayout.Y_AXIS);
268 this.setLayout(lo);
269 String[] choices = cb.getChoices();
270
271 if (cb.allowMultipleSelections()) {
272 for(int i = 0; i < choices.length; i++) {
273 boolean selected = (cb.getDefaultChoice() == i);
274 JCheckBox rb = new JCheckBox(choices[i], selected);
275 this.add(rb);
276 }
277
278 } else {
279 ButtonGroup group = new ButtonGroup();
280 for(int i = 0; i < choices.length; i++) {
281 boolean selected = (cb.getDefaultChoice() == i);
282 JRadioButton rb = new JRadioButton(choices[i], selected);
283 this.add(rb);
284 group.add(rb);
285 }
286 }
287 }
288
289 public void commit() {
290 Component[] comps = this.getComponents();
291
292 if (cb.allowMultipleSelections()) {
293 ArrayList indexes = new ArrayList(comps.length);
294 for(int i = 0; i < comps.length; i++) {
295 if (comps[i] instanceof JToggleButton) {
296 if (((JToggleButton) comps[i]).isSelected()) indexes.add(new Integer(i));
297 }
298 }
299
300 int[] choices = new int[indexes.size()];
301 for (int i = 0; i < indexes.size(); i++) {
302 int index = ((Integer) indexes.get(i)).intValue();
303 choices[i] = index;
304 }
305 cb.setSelectedIndexes(choices);
306 } else {
307 for(int i = 0; i < comps.length; i++) {
308 if (comps[i] instanceof JToggleButton) {
309 if (((JToggleButton) comps[i]).isSelected()) {
310 cb.setSelectedIndex(i);
311 }
312 }
313 }
314 }
315 }
316 }
317
318 class ConfirmationControl extends JPanel implements Commitable {
319 private ConfirmationCallback cb;
320 private int[] options;
321
322 public ConfirmationControl(ConfirmationCallback cb) {
323 this.cb = cb;
324 BoxLayout lo = new BoxLayout(this, BoxLayout.Y_AXIS);
325 this.setLayout(lo);
326 String[] choices = cb.getOptions();
327
328 if ((choices == null) || (cb.getOptionType() == ConfirmationCallback.UNSPECIFIED_OPTION)) {
329 switch (cb.getOptionType()) {
330 case ConfirmationCallback.OK_CANCEL_OPTION:
331 choices = new String[] { "Ok", "Cancel" };
332 options = new int[] { ConfirmationCallback.OK,
333 ConfirmationCallback.CANCEL };
334 break;
335
336 case ConfirmationCallback.YES_NO_CANCEL_OPTION:
337 choices = new String[] { "Yes", "No", "Cancel" };
338 options = new int[] { ConfirmationCallback.YES,
339 ConfirmationCallback.NO,
340 ConfirmationCallback.CANCEL };
341 break;
342
343 case ConfirmationCallback.YES_NO_OPTION:
344 choices = new String[] { "Yes", "No" };
345 options = new int[] { ConfirmationCallback.YES,
346 ConfirmationCallback.NO };
347 break;
348 }
349 }
350
351 ButtonGroup group = new ButtonGroup();
352 for(int i = 0; i < choices.length; i++) {
353 boolean selected = (cb.getDefaultOption() == i);
354 JRadioButton rb = new JRadioButton(choices[i], selected);
355 this.add(rb);
356 group.add(rb);
357 }
358 }
359
360 public void commit() {
361 Component[] comps = this.getComponents();
362
363 if (cb.getOptionType() == ConfirmationCallback.UNSPECIFIED_OPTION) {
364 for(int i = 0; i < comps.length; i++) {
365 if (comps[i] instanceof JToggleButton) {
366 if (((JToggleButton) comps[i]).isSelected()) {
367 cb.setSelectedIndex(i);
368 }
369 }
370 }
371 } else {
372 for(int i = 0; i < comps.length; i++) {
373 if (comps[i] instanceof JToggleButton) {
374 if (((JToggleButton) comps[i]).isSelected()) {
375 cb.setSelectedIndex(options[i]);
376 }
377 }
378 }
379 }
380 }
381 }
382 }