jdk/src/share/classes/com/sun/security/auth/callback/DialogCallbackHandler.java
changeset 22135 8c0cdd151b18
parent 22134 ae2d94255f32
parent 22132 e07e94d0c308
child 22142 53565ae5ac0f
equal deleted inserted replaced
22134:ae2d94255f32 22135:8c0cdd151b18
     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 }