All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.appclient.client.acc.callbackhandler.CallbackGUIBindings Maven / Gradle / Ivy

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package org.glassfish.appclient.client.acc.callbackhandler;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Vector;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.ChoiceCallback;
import javax.security.auth.callback.ConfirmationCallback;
import javax.security.auth.callback.LanguageCallback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.TextInputCallback;
import javax.security.auth.callback.TextOutputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.border.EtchedBorder;
import org.glassfish.appclient.client.acc.callbackhandler.CallbackBinding.GUI;

/**
 *
 * @author tjquinn
 */
public class CallbackGUIBindings {

    private static final Map callbackToBinding = initCallbackToBindingMap();

    private static Map initCallbackToBindingMap() {
        Map result = new HashMap();
        result.put(ChoiceCallback.class, Choice.class);
        result.put(ConfirmationCallback.class, Confirmation.class);
        result.put(LanguageCallback.class, Language.class);
        result.put(NameCallback.class, Name.class);
        result.put(PasswordCallback.class, Password.class);
        result.put(TextInputCallback.class, TextInput.class);
        result.put(TextOutputCallback.class, TextOutput.class);
        return result;
    }
    
    /**
     * Factory method for creating the appropriate callback-to-U/I binding
     * object given a callback.
     * @param callback the Callback for which to create the binding
     * @return the CallbackUIBinding suitable for the type of callback provided
     * @throws javax.security.auth.callback.UnsupportedCallbackException if the 
     * type of callback is not recognized
     */
    public Binding createCallbackGUIBinding(Callback callback) 
            throws UnsupportedCallbackException, InstantiationException, IllegalAccessException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
        
        Class bindingClass = callbackToBinding.get(callback.getClass());
        if (bindingClass != null) {
            Constructor constructor = 
                    bindingClass.getConstructor(
                        new Class[] { CallbackGUIBindings.class });
            Binding binding = constructor.newInstance(new Object[] { this });
            binding.setCallback(callback);
            return binding;
        }
        throw new UnsupportedCallbackException(callback);
    }    

    /**
     * Creates a default ConfirmationCallback binding (because the caller did
     * not provide one).
     * @return the default ConfirmationCallbackUIBinding
     */
    public CallbackGUIBindings.Confirmation getDefaultConfirmationCallbackUIBinding() {
        ConfirmationCallback defaultCallback = new ConfirmationCallback
                (ConfirmationCallback.INFORMATION,
                 ConfirmationCallback.OK_CANCEL_OPTION,
                 ConfirmationCallback.OK);

        CallbackGUIBindings.Confirmation binding = 
                new CallbackGUIBindings.Confirmation();
        binding.setCallback(defaultCallback);
        return binding;
    }
    
    /** number of rows to be visible in JLists used to display information*/
    protected static final int LIST_ROWS = 4;
    
    /** number of rows of text to be visible in text areas */
    protected static final int TEXT_ROWS = 4;
    
    /** number of columns for text areas */
    protected static final int TEXT_COLUMNS = 20;

    public abstract class Binding implements GUI {
        private JComponent component = null;

        protected C callback;

        protected JComponent createPromptedInputBox(String prompt, JComponent input) {
            Box box = new Box(BoxLayout.X_AXIS);
            JLabel promptLabel = new JLabel(prompt);
            box.add(promptLabel);
            box.add(input);
            return box;
        }

        protected MessageType getMessageType() {
            return null;
        }

        /**
         * Creates a JScrollPane containing the specified component with no
         * column header.
         * @param body the JComponent to enclose in the scroll pane
         * @return the JScrollPane holding the component
         */
        protected JScrollPane prepareScrollPane(JComponent body) {
            return new JScrollPane(body);
        }

        /**
         * Creates a JScrollPane containing a column header and the specified component.
         * @param columnHeader String containing the header text
         * @param body the JComponent to enclose in the scroll pane
         * @return the JScrollPane with the specified header and component 
         */
        protected JScrollPane prepareScrollPane(String columnHeader, JComponent body) {
            JScrollPane scrollPane = new JScrollPane(body);
            JLabel headerLabel = new JLabel(columnHeader);
            headerLabel.setBorder(new EtchedBorder(EtchedBorder.RAISED));
            scrollPane.setColumnHeaderView(headerLabel);
            return scrollPane;
        }

        protected abstract JComponent createComponent();

        public JComponent getComponent() {
            if (component == null) {
                component = createComponent();
            }
            return component;
        }

        @Override
        public void setCallback(C callback) {
            this.callback = callback;
        }
    }
    
    public class Choice extends Binding {
        /**
         * The binding for ChoiceCallbacks.
         */
        private JList jList;

        @Override
        protected JComponent createComponent() {
            jList = prepareList(
                        callback.getChoices(), 
                        callback.getSelectedIndexes());
            return prepareScrollPane(callback.getPrompt(), jList);
        }

        private JList prepareList(String[] choices, int[] selectedIndexes) {
            JList result = new JList();
            result.setVisibleRowCount(LIST_ROWS);
            result.setListData(choices);
            if (selectedIndexes != null) {
                result.setSelectedIndices(selectedIndexes);
            }
            result.setSelectionMode(this.callback.allowMultipleSelections() ? 
                ListSelectionModel.MULTIPLE_INTERVAL_SELECTION :
                ListSelectionModel.SINGLE_SELECTION);

            return result;
        }

        @Override
        public void finish() {
            if (callback.allowMultipleSelections()) {
                callback.setSelectedIndexes(jList.getSelectedIndices());
            } else {
                callback.setSelectedIndex(jList.getSelectedIndex());
            }
        }
    }

    public class Confirmation extends Binding {

        @Override
        protected JComponent createComponent() {
            return null;
        }

        @Override
        protected MessageType getMessageType() {
            return MessageType.severityForConfirmation(callback.getMessageType());
        }

        @Override
        public void finish() {
        }

        public int getOptionPaneOptionType() {
            if (callback.getOptionType() == ConfirmationCallback.OK_CANCEL_OPTION) {
                return JOptionPane.OK_CANCEL_OPTION;
            }
            if (callback.getOptionType() == ConfirmationCallback.YES_NO_CANCEL_OPTION) {
                return JOptionPane.YES_NO_CANCEL_OPTION;
            }
            if (callback.getOptionType() == ConfirmationCallback.YES_NO_OPTION) {
                return JOptionPane.YES_NO_OPTION;
            }
            return JOptionPane.OK_CANCEL_OPTION;
        }

        public String[] getOptions() {
            return callback.getOptions();
        }

        public int getDefaultOption() {
            return callback.getDefaultOption();
        }

        public void setResult(int result) {
            int callbackResult = -1;
            if (callback.getOptionType() == ConfirmationCallback.UNSPECIFIED_OPTION) {
                callbackResult = result;
            } else {
                if (callback.getOptionType() == ConfirmationCallback.OK_CANCEL_OPTION) {
                    if (result == JOptionPane.OK_OPTION) {
                        callbackResult = ConfirmationCallback.OK;
                    } else if (result == JOptionPane.CANCEL_OPTION) {
                        callbackResult = ConfirmationCallback.CANCEL;
                    }
                } else if (callback.getOptionType() == ConfirmationCallback.YES_NO_CANCEL_OPTION) {
                    if (result == JOptionPane.YES_OPTION) {
                        callbackResult = ConfirmationCallback.YES;
                    } else if (result == JOptionPane.NO_OPTION) {
                        callbackResult = ConfirmationCallback.NO;
                    } else if (result == JOptionPane.CANCEL_OPTION) {
                        callbackResult = ConfirmationCallback.CANCEL;
                    }
                } else if (callback.getOptionType() == ConfirmationCallback.YES_NO_OPTION) {
                    if (result == JOptionPane.YES_OPTION) {
                        callbackResult = ConfirmationCallback.YES;
                    } else if (result == JOptionPane.NO_OPTION) {
                        callbackResult = ConfirmationCallback.NO;
                    }                    
                }
            }
            callback.setSelectedIndex(callbackResult);
        }
    }

    public class Name extends Binding {

        private JTextField nameField;

        @Override
        protected JComponent createComponent() {
            JComponent result = createPromptedInputBox(
                        callback.getPrompt(),
                        nameField = new JTextField(callback.getDefaultName()));
            nameField.setColumns(20);
            return result;
        }

        @Override
        public void finish() {
             callback.setName(nameField.getText());
        }

    }

    public class Password extends Binding {
        private JPasswordField passwordField;

        @Override
        public JComponent createComponent() {
            JComponent result = createPromptedInputBox(
                    callback.getPrompt(),
                    passwordField = new JPasswordField());
            passwordField.setColumns(20);
            return result;
        }

        @Override
        public void finish() {
            callback.setPassword(passwordField.getPassword());
            passwordField.setText("");
        }
    }

    public class TextInput extends Binding {

        private JTextArea textArea;

        @Override
        public JComponent createComponent() {
            textArea = new JTextArea(
                    callback.getDefaultText(), 
                    TEXT_ROWS, 
                    TEXT_COLUMNS);
            textArea.setLineWrap(true);
            textArea.setWrapStyleWord(true);
            return prepareScrollPane(callback.getPrompt(), textArea);
        }

        @Override
        public void finish() {
            callback.setText(textArea.getText());
        }

    }

    public class TextOutput extends Binding {
        private JTextArea textArea;

        @Override
        public JComponent createComponent() {
            textArea = new JTextArea(this.callback.getMessage());
            textArea.setEditable(false);
            textArea.setWrapStyleWord(true);
            textArea.setLineWrap(true);
            textArea.setBackground(new JLabel().getBackground());
            return textArea;
        }

        @Override
        public void finish() {
        }

        @Override
        public MessageType getMessageType() {
            return MessageType.severityForTextOutput(callback.getMessageType());
        }
    }

    public class Language extends Binding {
        private JList languageList;

        @Override
        public JComponent createComponent() {

            Vector entries = new Vector();
            Locale defaultLocale = Locale.getDefault();
            LocaleEntry defaultEntry = null;
            Locale [] sortedLocales = Locale.getAvailableLocales();
            Arrays.sort(sortedLocales, 
                    new Comparator() {
                        @Override
                        public int compare(Locale l1, Locale l2) {
                            return l1.getDisplayName().compareTo(l2.getDisplayName());
                        }
                });
            for (Locale locale : sortedLocales) {
                LocaleEntry newEntry = new LocaleEntry(locale);
                entries.add(newEntry);
                if (locale.equals(defaultLocale)) {
                    defaultEntry = newEntry;
                }
            }

            languageList = new JList(entries);
            languageList.setVisibleRowCount(LIST_ROWS);
            languageList.setSelectedValue(defaultEntry, true);
            return prepareScrollPane(languageList);
        }

        @Override
        public void finish() {
            callback.setLocale(((LocaleEntry) languageList.getSelectedValue()).locale);
        }

        private class LocaleEntry {
            private Locale locale;

            private LocaleEntry(Locale locale) {
                this.locale = locale;
            }

            @Override
            public String toString() {
                return locale.getDisplayName();
            }


        }        
    }

    /**
     * Simplifies converting between option pane message types and callback
     * message types.
     */
    protected enum MessageType {
        /*
         * The message types must be defined in order of increasing severity.
         */
        PLAIN(JOptionPane.PLAIN_MESSAGE),
        INFORMATION(
                JOptionPane.INFORMATION_MESSAGE, 
                ConfirmationCallback.INFORMATION,
                TextOutputCallback.INFORMATION),
        QUESTION(JOptionPane.QUESTION_MESSAGE),
        WARNING(
                JOptionPane.WARNING_MESSAGE,
                ConfirmationCallback.WARNING,
                TextOutputCallback.WARNING),
        ERROR(
                JOptionPane.ERROR_MESSAGE,
                ConfirmationCallback.ERROR,
                TextOutputCallback.ERROR);
        
        private int optionPaneMessageType;
        private int confirmationCallbackMessageType;
        private int textOutputCallbackMessageType;
        private boolean mapsToCallback;
        
        private MessageType(int optionPaneMessageType) {
            this.optionPaneMessageType = optionPaneMessageType;
            mapsToCallback = false;
        }
        
        private MessageType(
                int optionPaneMessageType,
                int confirmationCallbackMessageType,
                int textOutputCallbackMessageType) {
            mapsToCallback = true;
            this.optionPaneMessageType = optionPaneMessageType;
            this.confirmationCallbackMessageType = confirmationCallbackMessageType;
            this.textOutputCallbackMessageType = textOutputCallbackMessageType;
        }
        
        public int getOptionPaneMessageType() {
            return optionPaneMessageType;
        }
        
        public boolean exceeds(MessageType ms) {
            return (ms == null) || ordinal() > ms.ordinal();
        }
        
        public static MessageType severityForConfirmation(
                int confirmationCallbackMessageType) {
            for (MessageType ms : values()) {
                if (ms.mapsToCallback && ms.confirmationCallbackMessageType == confirmationCallbackMessageType) {
                    return ms;
                }
            }
            throw new IllegalArgumentException(Integer.toString(confirmationCallbackMessageType));
        }
        
        public static MessageType severityForTextOutput(
                int textOutputCallbackMessageType) {
            for (MessageType ms : values()) {
                if (ms.mapsToCallback && ms.textOutputCallbackMessageType == textOutputCallbackMessageType) {
                    return ms;
                }
            }
            throw new IllegalArgumentException(Integer.toString(textOutputCallbackMessageType));
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy