changeset 9293:eecffec09621

8034943: Eliminate Kerberos dependency on com.sun.security.auth to avoid circular dependency Reviewed-by: weijun
author alanb
date Fri, 14 Feb 2014 15:21:26 +0000
parents c20c6a1eb13c
children 35e8d142f2d6
files src/share/classes/com/sun/security/auth/callback/TextCallbackHandler.java src/share/classes/sun/security/jgss/GSSUtil.java src/share/classes/sun/security/util/ConsoleCallbackHandler.java
diffstat 3 files changed, 258 insertions(+), 195 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/security/auth/callback/TextCallbackHandler.java	Fri Feb 14 11:23:58 2014 +0100
+++ b/src/share/classes/com/sun/security/auth/callback/TextCallbackHandler.java	Fri Feb 14 15:21:26 2014 +0000
@@ -28,21 +28,14 @@
 /* JAAS imports */
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.ConfirmationCallback;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.TextOutputCallback;
+import javax.security.auth.callback.NameCallback;        // javadoc
+import javax.security.auth.callback.PasswordCallback;    // javadoc
 import javax.security.auth.callback.UnsupportedCallbackException;
 
 /* Java imports */
-import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.PushbackInputStream;
-import java.util.Arrays;
 
-import sun.security.util.Password;
+import sun.security.util.ConsoleCallbackHandler;
 
 /**
  * <p>
@@ -55,6 +48,7 @@
 
 @jdk.Exported
 public class TextCallbackHandler implements CallbackHandler {
+    private final CallbackHandler consoleHandler;
 
     /**
      * <p>Creates a callback handler that prompts and reads from the
@@ -63,7 +57,9 @@
      * CallbackHandler.
 
      */
-    public TextCallbackHandler() { }
+    public TextCallbackHandler() {
+        this.consoleHandler = new ConsoleCallbackHandler();
+    }
 
     /**
      * Handles the specified set of callbacks.
@@ -76,187 +72,7 @@
     public void handle(Callback[] callbacks)
         throws IOException, UnsupportedCallbackException
     {
-        ConfirmationCallback confirmation = null;
-
-        for (int i = 0; i < callbacks.length; i++) {
-            if (callbacks[i] instanceof TextOutputCallback) {
-                TextOutputCallback tc = (TextOutputCallback) callbacks[i];
-
-                String text;
-                switch (tc.getMessageType()) {
-                case TextOutputCallback.INFORMATION:
-                    text = "";
-                    break;
-                case TextOutputCallback.WARNING:
-                    text = "Warning: ";
-                    break;
-                case TextOutputCallback.ERROR:
-                    text = "Error: ";
-                    break;
-                default:
-                    throw new UnsupportedCallbackException(
-                        callbacks[i], "Unrecognized message type");
-                }
-
-                String message = tc.getMessage();
-                if (message != null) {
-                    text += message;
-                }
-                if (text != null) {
-                    System.err.println(text);
-                }
-
-            } else if (callbacks[i] instanceof NameCallback) {
-                NameCallback nc = (NameCallback) callbacks[i];
-
-                if (nc.getDefaultName() == null) {
-                    System.err.print(nc.getPrompt());
-                } else {
-                    System.err.print(nc.getPrompt() +
-                                " [" + nc.getDefaultName() + "] ");
-                }
-                System.err.flush();
-
-                String result = readLine();
-                if (result.equals("")) {
-                    result = nc.getDefaultName();
-                }
-
-                nc.setName(result);
-
-            } else if (callbacks[i] instanceof PasswordCallback) {
-                PasswordCallback pc = (PasswordCallback) callbacks[i];
-
-                System.err.print(pc.getPrompt());
-                System.err.flush();
-
-                pc.setPassword(Password.readPassword(System.in, pc.isEchoOn()));
-
-            } else if (callbacks[i] instanceof ConfirmationCallback) {
-                confirmation = (ConfirmationCallback) callbacks[i];
-
-            } else {
-                throw new UnsupportedCallbackException(
-                    callbacks[i], "Unrecognized Callback");
-            }
-        }
-
-        /* Do the confirmation callback last. */
-        if (confirmation != null) {
-            doConfirmation(confirmation);
-        }
-    }
-
-    /* Reads a line of input */
-    private String readLine() throws IOException {
-        String result = new BufferedReader
-            (new InputStreamReader(System.in)).readLine();
-        if (result == null) {
-            throw new IOException("Cannot read from System.in");
-        }
-        return result;
-    }
-
-    private void doConfirmation(ConfirmationCallback confirmation)
-        throws IOException, UnsupportedCallbackException
-    {
-        String prefix;
-        int messageType = confirmation.getMessageType();
-        switch (messageType) {
-        case ConfirmationCallback.WARNING:
-            prefix =  "Warning: ";
-            break;
-        case ConfirmationCallback.ERROR:
-            prefix = "Error: ";
-            break;
-        case ConfirmationCallback.INFORMATION:
-            prefix = "";
-            break;
-        default:
-            throw new UnsupportedCallbackException(
-                confirmation, "Unrecognized message type: " + messageType);
-        }
-
-        class OptionInfo {
-            String name;
-            int value;
-            OptionInfo(String name, int value) {
-                this.name = name;
-                this.value = value;
-            }
-        }
-
-        OptionInfo[] options;
-        int optionType = confirmation.getOptionType();
-        switch (optionType) {
-        case ConfirmationCallback.YES_NO_OPTION:
-            options = new OptionInfo[] {
-                new OptionInfo("Yes", ConfirmationCallback.YES),
-                new OptionInfo("No", ConfirmationCallback.NO)
-            };
-            break;
-        case ConfirmationCallback.YES_NO_CANCEL_OPTION:
-            options = new OptionInfo[] {
-                new OptionInfo("Yes", ConfirmationCallback.YES),
-                new OptionInfo("No", ConfirmationCallback.NO),
-                new OptionInfo("Cancel", ConfirmationCallback.CANCEL)
-            };
-            break;
-        case ConfirmationCallback.OK_CANCEL_OPTION:
-            options = new OptionInfo[] {
-                new OptionInfo("OK", ConfirmationCallback.OK),
-                new OptionInfo("Cancel", ConfirmationCallback.CANCEL)
-            };
-            break;
-        case ConfirmationCallback.UNSPECIFIED_OPTION:
-            String[] optionStrings = confirmation.getOptions();
-            options = new OptionInfo[optionStrings.length];
-            for (int i = 0; i < options.length; i++) {
-                options[i] = new OptionInfo(optionStrings[i], i);
-            }
-            break;
-        default:
-            throw new UnsupportedCallbackException(
-                confirmation, "Unrecognized option type: " + optionType);
-        }
-
-        int defaultOption = confirmation.getDefaultOption();
-
-        String prompt = confirmation.getPrompt();
-        if (prompt == null) {
-            prompt = "";
-        }
-        prompt = prefix + prompt;
-        if (!prompt.equals("")) {
-            System.err.println(prompt);
-        }
-
-        for (int i = 0; i < options.length; i++) {
-            if (optionType == ConfirmationCallback.UNSPECIFIED_OPTION) {
-                // defaultOption is an index into the options array
-                System.err.println(
-                    i + ". " + options[i].name +
-                    (i == defaultOption ? " [default]" : ""));
-            } else {
-                // defaultOption is an option value
-                System.err.println(
-                    i + ". " + options[i].name +
-                    (options[i].value == defaultOption ? " [default]" : ""));
-            }
-        }
-        System.err.print("Enter a number: ");
-        System.err.flush();
-        int result;
-        try {
-            result = Integer.parseInt(readLine());
-            if (result < 0 || result > (options.length - 1)) {
-                result = defaultOption;
-            }
-            result = options[result].value;
-        } catch (NumberFormatException e) {
-            result = defaultOption;
-        }
-
-        confirmation.setSelectedIndex(result);
+        // delegate to console handler
+        consoleHandler.handle(callbacks);
     }
 }
--- a/src/share/classes/sun/security/jgss/GSSUtil.java	Fri Feb 14 11:23:58 2014 +0100
+++ b/src/share/classes/sun/security/jgss/GSSUtil.java	Fri Feb 14 15:21:26 2014 +0000
@@ -25,7 +25,6 @@
 
 package sun.security.jgss;
 
-import com.sun.security.auth.callback.TextCallbackHandler;
 import javax.security.auth.Subject;
 import javax.security.auth.kerberos.KerberosPrincipal;
 import javax.security.auth.kerberos.KerberosTicket;
@@ -48,6 +47,7 @@
 import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
 import sun.security.action.GetBooleanAction;
+import sun.security.util.ConsoleCallbackHandler;
 
 /**
  * The GSSUtilImplementation that knows how to work with the internals of
@@ -243,7 +243,7 @@
             if ((defaultHandler != null) && (defaultHandler.length() != 0)) {
                 cb = null;
             } else {
-                cb = new TextCallbackHandler();
+                cb = new ConsoleCallbackHandler();
             }
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/util/ConsoleCallbackHandler.java	Fri Feb 14 15:21:26 2014 +0000
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.util;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.ConfirmationCallback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextOutputCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+/**
+ * A {@code CallbackHandler} that prompts and reads from the command line
+ * for answers to authentication questions.
+ */
+public class ConsoleCallbackHandler implements CallbackHandler {
+
+    /**
+     * Creates a callback handler that prompts and reads from the
+     * command line for answers to authentication questions.
+     */
+    public ConsoleCallbackHandler() { }
+
+    /**
+     * Handles the specified set of callbacks.
+     *
+     * @param callbacks the callbacks to handle
+     * @throws IOException if an input or output error occurs.
+     * @throws UnsupportedCallbackException if the callback is not an
+     * instance of NameCallback or PasswordCallback
+     */
+    public void handle(Callback[] callbacks)
+        throws IOException, UnsupportedCallbackException
+    {
+        ConfirmationCallback confirmation = null;
+
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof TextOutputCallback) {
+                TextOutputCallback tc = (TextOutputCallback) callbacks[i];
+
+                String text;
+                switch (tc.getMessageType()) {
+                case TextOutputCallback.INFORMATION:
+                    text = "";
+                    break;
+                case TextOutputCallback.WARNING:
+                    text = "Warning: ";
+                    break;
+                case TextOutputCallback.ERROR:
+                    text = "Error: ";
+                    break;
+                default:
+                    throw new UnsupportedCallbackException(
+                        callbacks[i], "Unrecognized message type");
+                }
+
+                String message = tc.getMessage();
+                if (message != null) {
+                    text += message;
+                }
+                if (text != null) {
+                    System.err.println(text);
+                }
+
+            } else if (callbacks[i] instanceof NameCallback) {
+                NameCallback nc = (NameCallback) callbacks[i];
+
+                if (nc.getDefaultName() == null) {
+                    System.err.print(nc.getPrompt());
+                } else {
+                    System.err.print(nc.getPrompt() +
+                                " [" + nc.getDefaultName() + "] ");
+                }
+                System.err.flush();
+
+                String result = readLine();
+                if (result.equals("")) {
+                    result = nc.getDefaultName();
+                }
+
+                nc.setName(result);
+
+            } else if (callbacks[i] instanceof PasswordCallback) {
+                PasswordCallback pc = (PasswordCallback) callbacks[i];
+
+                System.err.print(pc.getPrompt());
+                System.err.flush();
+
+                pc.setPassword(Password.readPassword(System.in, pc.isEchoOn()));
+
+            } else if (callbacks[i] instanceof ConfirmationCallback) {
+                confirmation = (ConfirmationCallback) callbacks[i];
+
+            } else {
+                throw new UnsupportedCallbackException(
+                    callbacks[i], "Unrecognized Callback");
+            }
+        }
+
+        /* Do the confirmation callback last. */
+        if (confirmation != null) {
+            doConfirmation(confirmation);
+        }
+    }
+
+    /* Reads a line of input */
+    private String readLine() throws IOException {
+        String result = new BufferedReader
+            (new InputStreamReader(System.in)).readLine();
+        if (result == null) {
+            throw new IOException("Cannot read from System.in");
+        }
+        return result;
+    }
+
+    private void doConfirmation(ConfirmationCallback confirmation)
+        throws IOException, UnsupportedCallbackException
+    {
+        String prefix;
+        int messageType = confirmation.getMessageType();
+        switch (messageType) {
+        case ConfirmationCallback.WARNING:
+            prefix =  "Warning: ";
+            break;
+        case ConfirmationCallback.ERROR:
+            prefix = "Error: ";
+            break;
+        case ConfirmationCallback.INFORMATION:
+            prefix = "";
+            break;
+        default:
+            throw new UnsupportedCallbackException(
+                confirmation, "Unrecognized message type: " + messageType);
+        }
+
+        class OptionInfo {
+            String name;
+            int value;
+            OptionInfo(String name, int value) {
+                this.name = name;
+                this.value = value;
+            }
+        }
+
+        OptionInfo[] options;
+        int optionType = confirmation.getOptionType();
+        switch (optionType) {
+        case ConfirmationCallback.YES_NO_OPTION:
+            options = new OptionInfo[] {
+                new OptionInfo("Yes", ConfirmationCallback.YES),
+                new OptionInfo("No", ConfirmationCallback.NO)
+            };
+            break;
+        case ConfirmationCallback.YES_NO_CANCEL_OPTION:
+            options = new OptionInfo[] {
+                new OptionInfo("Yes", ConfirmationCallback.YES),
+                new OptionInfo("No", ConfirmationCallback.NO),
+                new OptionInfo("Cancel", ConfirmationCallback.CANCEL)
+            };
+            break;
+        case ConfirmationCallback.OK_CANCEL_OPTION:
+            options = new OptionInfo[] {
+                new OptionInfo("OK", ConfirmationCallback.OK),
+                new OptionInfo("Cancel", ConfirmationCallback.CANCEL)
+            };
+            break;
+        case ConfirmationCallback.UNSPECIFIED_OPTION:
+            String[] optionStrings = confirmation.getOptions();
+            options = new OptionInfo[optionStrings.length];
+            for (int i = 0; i < options.length; i++) {
+                options[i] = new OptionInfo(optionStrings[i], i);
+            }
+            break;
+        default:
+            throw new UnsupportedCallbackException(
+                confirmation, "Unrecognized option type: " + optionType);
+        }
+
+        int defaultOption = confirmation.getDefaultOption();
+
+        String prompt = confirmation.getPrompt();
+        if (prompt == null) {
+            prompt = "";
+        }
+        prompt = prefix + prompt;
+        if (!prompt.equals("")) {
+            System.err.println(prompt);
+        }
+
+        for (int i = 0; i < options.length; i++) {
+            if (optionType == ConfirmationCallback.UNSPECIFIED_OPTION) {
+                // defaultOption is an index into the options array
+                System.err.println(
+                    i + ". " + options[i].name +
+                    (i == defaultOption ? " [default]" : ""));
+            } else {
+                // defaultOption is an option value
+                System.err.println(
+                    i + ". " + options[i].name +
+                    (options[i].value == defaultOption ? " [default]" : ""));
+            }
+        }
+        System.err.print("Enter a number: ");
+        System.err.flush();
+        int result;
+        try {
+            result = Integer.parseInt(readLine());
+            if (result < 0 || result > (options.length - 1)) {
+                result = defaultOption;
+            }
+            result = options[result].value;
+        } catch (NumberFormatException e) {
+            result = defaultOption;
+        }
+
+        confirmation.setSelectedIndex(result);
+    }
+}