1 /* |
|
2 * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Oracle designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Oracle in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 * or visit www.oracle.com if you need additional information or have any |
|
23 * questions. |
|
24 */ |
|
25 |
|
26 package com.sun.security.auth.callback; |
|
27 |
|
28 /* JAAS imports */ |
|
29 import javax.security.auth.callback.Callback; |
|
30 import javax.security.auth.callback.CallbackHandler; |
|
31 import javax.security.auth.callback.ConfirmationCallback; |
|
32 import javax.security.auth.callback.NameCallback; |
|
33 import javax.security.auth.callback.PasswordCallback; |
|
34 import javax.security.auth.callback.TextOutputCallback; |
|
35 import javax.security.auth.callback.UnsupportedCallbackException; |
|
36 |
|
37 /* Java imports */ |
|
38 import java.awt.Component; |
|
39 import java.util.ArrayList; |
|
40 import java.util.Iterator; |
|
41 import java.util.List; |
|
42 import javax.swing.Box; |
|
43 import javax.swing.JLabel; |
|
44 import javax.swing.JOptionPane; |
|
45 import javax.swing.JPasswordField; |
|
46 import javax.swing.JTextField; |
|
47 |
|
48 /** |
|
49 * <p> |
|
50 * Uses a Swing dialog window to query the user for answers to |
|
51 * authentication questions. |
|
52 * This can be used by a JAAS application to instantiate a |
|
53 * CallbackHandler |
|
54 * @see javax.security.auth.callback |
|
55 * @deprecated This class will be removed in a future release. |
|
56 */ |
|
57 @jdk.Exported(false) |
|
58 @Deprecated |
|
59 public class DialogCallbackHandler implements CallbackHandler { |
|
60 |
|
61 /* -- Fields -- */ |
|
62 |
|
63 /* The parent window, or null if using the default parent */ |
|
64 private Component parentComponent; |
|
65 private static final int JPasswordFieldLen = 8 ; |
|
66 private static final int JTextFieldLen = 8 ; |
|
67 |
|
68 /* -- Methods -- */ |
|
69 |
|
70 /** |
|
71 * Creates a callback dialog with the default parent window. |
|
72 */ |
|
73 public DialogCallbackHandler() { } |
|
74 |
|
75 /** |
|
76 * Creates a callback dialog and specify the parent window. |
|
77 * |
|
78 * @param parentComponent the parent window -- specify <code>null</code> |
|
79 * for the default parent |
|
80 */ |
|
81 public DialogCallbackHandler(Component parentComponent) { |
|
82 this.parentComponent = parentComponent; |
|
83 } |
|
84 |
|
85 /* |
|
86 * An interface for recording actions to carry out if the user |
|
87 * clicks OK for the dialog. |
|
88 */ |
|
89 private static interface Action { |
|
90 void perform(); |
|
91 } |
|
92 |
|
93 /** |
|
94 * Handles the specified set of callbacks. |
|
95 * |
|
96 * @param callbacks the callbacks to handle |
|
97 * @throws UnsupportedCallbackException if the callback is not an |
|
98 * instance of NameCallback or PasswordCallback |
|
99 */ |
|
100 |
|
101 public void handle(Callback[] callbacks) |
|
102 throws UnsupportedCallbackException |
|
103 { |
|
104 /* Collect messages to display in the dialog */ |
|
105 final List<Object> messages = new ArrayList<>(3); |
|
106 |
|
107 /* Collection actions to perform if the user clicks OK */ |
|
108 final List<Action> okActions = new ArrayList<>(2); |
|
109 |
|
110 ConfirmationInfo confirmation = new ConfirmationInfo(); |
|
111 |
|
112 for (int i = 0; i < callbacks.length; i++) { |
|
113 if (callbacks[i] instanceof TextOutputCallback) { |
|
114 TextOutputCallback tc = (TextOutputCallback) callbacks[i]; |
|
115 |
|
116 switch (tc.getMessageType()) { |
|
117 case TextOutputCallback.INFORMATION: |
|
118 confirmation.messageType = JOptionPane.INFORMATION_MESSAGE; |
|
119 break; |
|
120 case TextOutputCallback.WARNING: |
|
121 confirmation.messageType = JOptionPane.WARNING_MESSAGE; |
|
122 break; |
|
123 case TextOutputCallback.ERROR: |
|
124 confirmation.messageType = JOptionPane.ERROR_MESSAGE; |
|
125 break; |
|
126 default: |
|
127 throw new UnsupportedCallbackException( |
|
128 callbacks[i], "Unrecognized message type"); |
|
129 } |
|
130 |
|
131 messages.add(tc.getMessage()); |
|
132 |
|
133 } else if (callbacks[i] instanceof NameCallback) { |
|
134 final NameCallback nc = (NameCallback) callbacks[i]; |
|
135 |
|
136 JLabel prompt = new JLabel(nc.getPrompt()); |
|
137 |
|
138 final JTextField name = new JTextField(JTextFieldLen); |
|
139 String defaultName = nc.getDefaultName(); |
|
140 if (defaultName != null) { |
|
141 name.setText(defaultName); |
|
142 } |
|
143 |
|
144 /* |
|
145 * Put the prompt and name in a horizontal box, |
|
146 * and add that to the set of messages. |
|
147 */ |
|
148 Box namePanel = Box.createHorizontalBox(); |
|
149 namePanel.add(prompt); |
|
150 namePanel.add(name); |
|
151 messages.add(namePanel); |
|
152 |
|
153 /* Store the name back into the callback if OK */ |
|
154 okActions.add(new Action() { |
|
155 public void perform() { |
|
156 nc.setName(name.getText()); |
|
157 } |
|
158 }); |
|
159 |
|
160 } else if (callbacks[i] instanceof PasswordCallback) { |
|
161 final PasswordCallback pc = (PasswordCallback) callbacks[i]; |
|
162 |
|
163 JLabel prompt = new JLabel(pc.getPrompt()); |
|
164 |
|
165 final JPasswordField password = |
|
166 new JPasswordField(JPasswordFieldLen); |
|
167 if (!pc.isEchoOn()) { |
|
168 password.setEchoChar('*'); |
|
169 } |
|
170 |
|
171 Box passwordPanel = Box.createHorizontalBox(); |
|
172 passwordPanel.add(prompt); |
|
173 passwordPanel.add(password); |
|
174 messages.add(passwordPanel); |
|
175 |
|
176 okActions.add(new Action() { |
|
177 public void perform() { |
|
178 pc.setPassword(password.getPassword()); |
|
179 } |
|
180 }); |
|
181 |
|
182 } else if (callbacks[i] instanceof ConfirmationCallback) { |
|
183 ConfirmationCallback cc = (ConfirmationCallback)callbacks[i]; |
|
184 |
|
185 confirmation.setCallback(cc); |
|
186 if (cc.getPrompt() != null) { |
|
187 messages.add(cc.getPrompt()); |
|
188 } |
|
189 |
|
190 } else { |
|
191 throw new UnsupportedCallbackException( |
|
192 callbacks[i], "Unrecognized Callback"); |
|
193 } |
|
194 } |
|
195 |
|
196 /* Display the dialog */ |
|
197 int result = JOptionPane.showOptionDialog( |
|
198 parentComponent, |
|
199 messages.toArray(), |
|
200 "Confirmation", /* title */ |
|
201 confirmation.optionType, |
|
202 confirmation.messageType, |
|
203 null, /* icon */ |
|
204 confirmation.options, /* options */ |
|
205 confirmation.initialValue); /* initialValue */ |
|
206 |
|
207 /* Perform the OK actions */ |
|
208 if (result == JOptionPane.OK_OPTION |
|
209 || result == JOptionPane.YES_OPTION) |
|
210 { |
|
211 Iterator<Action> iterator = okActions.iterator(); |
|
212 while (iterator.hasNext()) { |
|
213 iterator.next().perform(); |
|
214 } |
|
215 } |
|
216 confirmation.handleResult(result); |
|
217 } |
|
218 |
|
219 /* |
|
220 * Provides assistance with translating between JAAS and Swing |
|
221 * confirmation dialogs. |
|
222 */ |
|
223 private static class ConfirmationInfo { |
|
224 |
|
225 private int[] translations; |
|
226 |
|
227 int optionType = JOptionPane.OK_CANCEL_OPTION; |
|
228 Object[] options = null; |
|
229 Object initialValue = null; |
|
230 |
|
231 int messageType = JOptionPane.QUESTION_MESSAGE; |
|
232 |
|
233 private ConfirmationCallback callback; |
|
234 |
|
235 /* Set the confirmation callback handler */ |
|
236 void setCallback(ConfirmationCallback callback) |
|
237 throws UnsupportedCallbackException |
|
238 { |
|
239 this.callback = callback; |
|
240 |
|
241 int confirmationOptionType = callback.getOptionType(); |
|
242 switch (confirmationOptionType) { |
|
243 case ConfirmationCallback.YES_NO_OPTION: |
|
244 optionType = JOptionPane.YES_NO_OPTION; |
|
245 translations = new int[] { |
|
246 JOptionPane.YES_OPTION, ConfirmationCallback.YES, |
|
247 JOptionPane.NO_OPTION, ConfirmationCallback.NO, |
|
248 JOptionPane.CLOSED_OPTION, ConfirmationCallback.NO |
|
249 }; |
|
250 break; |
|
251 case ConfirmationCallback.YES_NO_CANCEL_OPTION: |
|
252 optionType = JOptionPane.YES_NO_CANCEL_OPTION; |
|
253 translations = new int[] { |
|
254 JOptionPane.YES_OPTION, ConfirmationCallback.YES, |
|
255 JOptionPane.NO_OPTION, ConfirmationCallback.NO, |
|
256 JOptionPane.CANCEL_OPTION, ConfirmationCallback.CANCEL, |
|
257 JOptionPane.CLOSED_OPTION, ConfirmationCallback.CANCEL |
|
258 }; |
|
259 break; |
|
260 case ConfirmationCallback.OK_CANCEL_OPTION: |
|
261 optionType = JOptionPane.OK_CANCEL_OPTION; |
|
262 translations = new int[] { |
|
263 JOptionPane.OK_OPTION, ConfirmationCallback.OK, |
|
264 JOptionPane.CANCEL_OPTION, ConfirmationCallback.CANCEL, |
|
265 JOptionPane.CLOSED_OPTION, ConfirmationCallback.CANCEL |
|
266 }; |
|
267 break; |
|
268 case ConfirmationCallback.UNSPECIFIED_OPTION: |
|
269 options = callback.getOptions(); |
|
270 /* |
|
271 * There's no way to know if the default option means |
|
272 * to cancel the login, but there isn't a better way |
|
273 * to guess this. |
|
274 */ |
|
275 translations = new int[] { |
|
276 JOptionPane.CLOSED_OPTION, callback.getDefaultOption() |
|
277 }; |
|
278 break; |
|
279 default: |
|
280 throw new UnsupportedCallbackException( |
|
281 callback, |
|
282 "Unrecognized option type: " + confirmationOptionType); |
|
283 } |
|
284 |
|
285 int confirmationMessageType = callback.getMessageType(); |
|
286 switch (confirmationMessageType) { |
|
287 case ConfirmationCallback.WARNING: |
|
288 messageType = JOptionPane.WARNING_MESSAGE; |
|
289 break; |
|
290 case ConfirmationCallback.ERROR: |
|
291 messageType = JOptionPane.ERROR_MESSAGE; |
|
292 break; |
|
293 case ConfirmationCallback.INFORMATION: |
|
294 messageType = JOptionPane.INFORMATION_MESSAGE; |
|
295 break; |
|
296 default: |
|
297 throw new UnsupportedCallbackException( |
|
298 callback, |
|
299 "Unrecognized message type: " + confirmationMessageType); |
|
300 } |
|
301 } |
|
302 |
|
303 |
|
304 /* Process the result returned by the Swing dialog */ |
|
305 void handleResult(int result) { |
|
306 if (callback == null) { |
|
307 return; |
|
308 } |
|
309 |
|
310 for (int i = 0; i < translations.length; i += 2) { |
|
311 if (translations[i] == result) { |
|
312 result = translations[i + 1]; |
|
313 break; |
|
314 } |
|
315 } |
|
316 callback.setSelectedIndex(result); |
|
317 } |
|
318 } |
|
319 } |
|