1 /*
   2  * Copyright (c) 1999, 2019, 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 javax.security.auth.callback;
  27 
  28 /**
  29  * <p> Underlying security services instantiate and pass a
  30  * {@code ConfirmationCallback} to the {@code handle}
  31  * method of a {@code CallbackHandler} to ask for YES/NO,
  32  * OK/CANCEL, YES/NO/CANCEL or other similar confirmations.
  33  *
  34  * @since 1.4
  35  * @see javax.security.auth.callback.CallbackHandler
  36  */
  37 public class ConfirmationCallback implements Callback, java.io.Serializable {
  38 
  39     private static final long serialVersionUID = -9095656433782481624L;
  40 
  41     /**
  42      * Unspecified option type.
  43      *
  44      * <p> The {@code getOptionType} method returns this
  45      * value if this {@code ConfirmationCallback} was instantiated
  46      * with {@code options} instead of an {@code optionType}.
  47      */
  48     public static final int UNSPECIFIED_OPTION          = -1;
  49 
  50     /**
  51      * YES/NO confirmation option.
  52      *
  53      * <p> An underlying security service specifies this as the
  54      * {@code optionType} to a {@code ConfirmationCallback}
  55      * constructor if it requires a confirmation which can be answered
  56      * with either {@code YES} or {@code NO}.
  57      */
  58     public static final int YES_NO_OPTION               = 0;
  59 
  60     /**
  61      * YES/NO/CANCEL confirmation option.
  62      *
  63      * <p> An underlying security service specifies this as the
  64      * {@code optionType} to a {@code ConfirmationCallback}
  65      * constructor if it requires a confirmation which can be answered
  66      * with either {@code YES}, {@code NO} or {@code CANCEL}.
  67      */
  68     public static final int YES_NO_CANCEL_OPTION        = 1;
  69 
  70     /**
  71      * OK/CANCEL confirmation option.
  72      *
  73      * <p> An underlying security service specifies this as the
  74      * {@code optionType} to a {@code ConfirmationCallback}
  75      * constructor if it requires a confirmation which can be answered
  76      * with either {@code OK} or {@code CANCEL}.
  77      */
  78     public static final int OK_CANCEL_OPTION            = 2;
  79 
  80     /**
  81      * YES option.
  82      *
  83      * <p> If an {@code optionType} was specified to this
  84      * {@code ConfirmationCallback}, this option may be specified as a
  85      * {@code defaultOption} or returned as the selected index.
  86      */
  87     public static final int YES                         = 0;
  88 
  89     /**
  90      * NO option.
  91      *
  92      * <p> If an {@code optionType} was specified to this
  93      * {@code ConfirmationCallback}, this option may be specified as a
  94      * {@code defaultOption} or returned as the selected index.
  95      */
  96     public static final int NO                          = 1;
  97 
  98     /**
  99      * CANCEL option.
 100      *
 101      * <p> If an {@code optionType} was specified to this
 102      * {@code ConfirmationCallback}, this option may be specified as a
 103      * {@code defaultOption} or returned as the selected index.
 104      */
 105     public static final int CANCEL                      = 2;
 106 
 107     /**
 108      * OK option.
 109      *
 110      * <p> If an {@code optionType} was specified to this
 111      * {@code ConfirmationCallback}, this option may be specified as a
 112      * {@code defaultOption} or returned as the selected index.
 113      */
 114     public static final int OK                          = 3;
 115 
 116     /** INFORMATION message type.  */
 117     public static final int INFORMATION                 = 0;
 118 
 119     /** WARNING message type. */
 120     public static final int WARNING                     = 1;
 121 
 122     /** ERROR message type. */
 123     public static final int ERROR                       = 2;
 124     /**
 125      * @serial
 126      * @since 1.4
 127      */
 128     private String prompt;
 129     /**
 130      * @serial
 131      * @since 1.4
 132      */
 133     private int messageType;
 134     /**
 135      * @serial
 136      * @since 1.4
 137      */
 138     private int optionType = UNSPECIFIED_OPTION;
 139     /**
 140      * @serial
 141      * @since 1.4
 142      */
 143     private int defaultOption;
 144     /**
 145      * @serial
 146      * @since 1.4
 147      */
 148     private String[] options;
 149     /**
 150      * @serial
 151      * @since 1.4
 152      */
 153     private int selection;
 154 
 155     /**
 156      * Construct a {@code ConfirmationCallback} with a
 157      * message type, an option type and a default option.
 158      *
 159      * <p> Underlying security services use this constructor if
 160      * they require either a YES/NO, YES/NO/CANCEL or OK/CANCEL
 161      * confirmation.
 162      *
 163      * @param messageType the message type ({@code INFORMATION},
 164      *                  {@code WARNING} or {@code ERROR}).
 165      *
 166      * @param optionType the option type ({@code YES_NO_OPTION},
 167      *                  {@code YES_NO_CANCEL_OPTION} or
 168      *                  {@code OK_CANCEL_OPTION}).
 169      *
 170      * @param defaultOption the default option
 171      *                  from the provided optionType ({@code YES},
 172      *                  {@code NO}, {@code CANCEL} or
 173      *                  {@code OK}).
 174      *
 175      * @exception IllegalArgumentException if messageType is not either
 176      *                  {@code INFORMATION}, {@code WARNING},
 177      *                  or {@code ERROR}, if optionType is not either
 178      *                  {@code YES_NO_OPTION},
 179      *                  {@code YES_NO_CANCEL_OPTION}, or
 180      *                  {@code OK_CANCEL_OPTION},
 181      *                  or if {@code defaultOption}
 182      *                  does not correspond to one of the options in
 183      *                  {@code optionType}.
 184      */
 185     public ConfirmationCallback(int messageType,
 186                 int optionType, int defaultOption) {
 187 
 188         if (messageType < INFORMATION || messageType > ERROR ||
 189             optionType < YES_NO_OPTION || optionType > OK_CANCEL_OPTION)
 190             throw new IllegalArgumentException();
 191 
 192         switch (optionType) {
 193         case YES_NO_OPTION:
 194             if (defaultOption != YES && defaultOption != NO)
 195                 throw new IllegalArgumentException();
 196             break;
 197         case YES_NO_CANCEL_OPTION:
 198             if (defaultOption != YES && defaultOption != NO &&
 199                 defaultOption != CANCEL)
 200                 throw new IllegalArgumentException();
 201             break;
 202         case OK_CANCEL_OPTION:
 203             if (defaultOption != OK && defaultOption != CANCEL)
 204                 throw new IllegalArgumentException();
 205             break;
 206         }
 207 
 208         this.messageType = messageType;
 209         this.optionType = optionType;
 210         this.defaultOption = defaultOption;
 211     }
 212 
 213     /**
 214      * Construct a {@code ConfirmationCallback} with a
 215      * message type, a list of options and a default option.
 216      *
 217      * <p> Underlying security services use this constructor if
 218      * they require a confirmation different from the available preset
 219      * confirmations provided (for example, CONTINUE/ABORT or STOP/GO).
 220      * The confirmation options are listed in the {@code options} array,
 221      * and are displayed by the {@code CallbackHandler} implementation
 222      * in a manner consistent with the way preset options are displayed.
 223      *
 224      * @param messageType the message type ({@code INFORMATION},
 225      *                  {@code WARNING} or {@code ERROR}).
 226      *
 227      * @param options the list of confirmation options.
 228      *
 229      * @param defaultOption the default option, represented as an index
 230      *                  into the {@code options} array.
 231      *
 232      * @exception IllegalArgumentException if messageType is not either
 233      *                  {@code INFORMATION}, {@code WARNING},
 234      *                  or {@code ERROR}, if {@code options} is null,
 235      *                  if {@code options} has a length of 0,
 236      *                  if any element from {@code options} is null,
 237      *                  if any element from {@code options}
 238      *                  has a length of 0, or if {@code defaultOption}
 239      *                  does not lie within the array boundaries of
 240      *                  {@code options}.
 241      */
 242     public ConfirmationCallback(int messageType,
 243                 String[] options, int defaultOption) {
 244 
 245         if (messageType < INFORMATION || messageType > ERROR ||
 246             options == null || options.length == 0 ||
 247             defaultOption < 0 || defaultOption >= options.length)
 248             throw new IllegalArgumentException();
 249 
 250         for (int i = 0; i < options.length; i++) {
 251             if (options[i] == null || options[i].isEmpty())
 252                 throw new IllegalArgumentException();
 253         }
 254 
 255         this.messageType = messageType;
 256         this.options = options;
 257         this.defaultOption = defaultOption;
 258     }
 259 
 260     /**
 261      * Construct a {@code ConfirmationCallback} with a prompt,
 262      * message type, an option type and a default option.
 263      *
 264      * <p> Underlying security services use this constructor if
 265      * they require either a YES/NO, YES/NO/CANCEL or OK/CANCEL
 266      * confirmation.
 267      *
 268      * @param prompt the prompt used to describe the list of options.
 269      *
 270      * @param messageType the message type ({@code INFORMATION},
 271      *                  {@code WARNING} or {@code ERROR}).
 272      *
 273      * @param optionType the option type ({@code YES_NO_OPTION},
 274      *                  {@code YES_NO_CANCEL_OPTION} or
 275      *                  {@code OK_CANCEL_OPTION}).
 276      *
 277      * @param defaultOption the default option
 278      *                  from the provided optionType ({@code YES},
 279      *                  {@code NO}, {@code CANCEL} or
 280      *                  {@code OK}).
 281      *
 282      * @exception IllegalArgumentException if {@code prompt} is null,
 283      *                  if {@code prompt} has a length of 0,
 284      *                  if messageType is not either
 285      *                  {@code INFORMATION}, {@code WARNING},
 286      *                  or {@code ERROR}, if optionType is not either
 287      *                  {@code YES_NO_OPTION},
 288      *                  {@code YES_NO_CANCEL_OPTION}, or
 289      *                  {@code OK_CANCEL_OPTION},
 290      *                  or if {@code defaultOption}
 291      *                  does not correspond to one of the options in
 292      *                  {@code optionType}.
 293      */
 294     public ConfirmationCallback(String prompt, int messageType,
 295                 int optionType, int defaultOption) {
 296 
 297         if (prompt == null || prompt.isEmpty() ||
 298             messageType < INFORMATION || messageType > ERROR ||
 299             optionType < YES_NO_OPTION || optionType > OK_CANCEL_OPTION)
 300             throw new IllegalArgumentException();
 301 
 302         switch (optionType) {
 303         case YES_NO_OPTION:
 304             if (defaultOption != YES && defaultOption != NO)
 305                 throw new IllegalArgumentException();
 306             break;
 307         case YES_NO_CANCEL_OPTION:
 308             if (defaultOption != YES && defaultOption != NO &&
 309                 defaultOption != CANCEL)
 310                 throw new IllegalArgumentException();
 311             break;
 312         case OK_CANCEL_OPTION:
 313             if (defaultOption != OK && defaultOption != CANCEL)
 314                 throw new IllegalArgumentException();
 315             break;
 316         }
 317 
 318         this.prompt = prompt;
 319         this.messageType = messageType;
 320         this.optionType = optionType;
 321         this.defaultOption = defaultOption;
 322     }
 323 
 324     /**
 325      * Construct a {@code ConfirmationCallback} with a prompt,
 326      * message type, a list of options and a default option.
 327      *
 328      * <p> Underlying security services use this constructor if
 329      * they require a confirmation different from the available preset
 330      * confirmations provided (for example, CONTINUE/ABORT or STOP/GO).
 331      * The confirmation options are listed in the {@code options} array,
 332      * and are displayed by the {@code CallbackHandler} implementation
 333      * in a manner consistent with the way preset options are displayed.
 334      *
 335      * @param prompt the prompt used to describe the list of options.
 336      *
 337      * @param messageType the message type ({@code INFORMATION},
 338      *                  {@code WARNING} or {@code ERROR}).
 339      *
 340      * @param options the list of confirmation options.
 341      *
 342      * @param defaultOption the default option, represented as an index
 343      *                  into the {@code options} array.
 344      *
 345      * @exception IllegalArgumentException if {@code prompt} is null,
 346      *                  if {@code prompt} has a length of 0,
 347      *                  if messageType is not either
 348      *                  {@code INFORMATION}, {@code WARNING},
 349      *                  or {@code ERROR}, if {@code options} is null,
 350      *                  if {@code options} has a length of 0,
 351      *                  if any element from {@code options} is null,
 352      *                  if any element from {@code options}
 353      *                  has a length of 0, or if {@code defaultOption}
 354      *                  does not lie within the array boundaries of
 355      *                  {@code options}.
 356      */
 357     public ConfirmationCallback(String prompt, int messageType,
 358                 String[] options, int defaultOption) {
 359 
 360         if (prompt == null || prompt.isEmpty() ||
 361             messageType < INFORMATION || messageType > ERROR ||
 362             options == null || options.length == 0 ||
 363             defaultOption < 0 || defaultOption >= options.length)
 364             throw new IllegalArgumentException();
 365 
 366         for (int i = 0; i < options.length; i++) {
 367             if (options[i] == null || options[i].isEmpty())
 368                 throw new IllegalArgumentException();
 369         }
 370 
 371         this.prompt = prompt;
 372         this.messageType = messageType;
 373         this.options = options;
 374         this.defaultOption = defaultOption;
 375     }
 376 
 377     /**
 378      * Get the prompt.
 379      *
 380      * @return the prompt, or null if this {@code ConfirmationCallback}
 381      *          was instantiated without a {@code prompt}.
 382      */
 383     public String getPrompt() {
 384         return prompt;
 385     }
 386 
 387     /**
 388      * Get the message type.
 389      *
 390      * @return the message type ({@code INFORMATION},
 391      *          {@code WARNING} or {@code ERROR}).
 392      */
 393     public int getMessageType() {
 394         return messageType;
 395     }
 396 
 397     /**
 398      * Get the option type.
 399      *
 400      * <p> If this method returns {@code UNSPECIFIED_OPTION}, then this
 401      * {@code ConfirmationCallback} was instantiated with
 402      * {@code options} instead of an {@code optionType}.
 403      * In this case, invoke the {@code getOptions} method
 404      * to determine which confirmation options to display.
 405      *
 406      * @return the option type ({@code YES_NO_OPTION},
 407      *          {@code YES_NO_CANCEL_OPTION} or
 408      *          {@code OK_CANCEL_OPTION}), or
 409      *          {@code UNSPECIFIED_OPTION} if this
 410      *          {@code ConfirmationCallback} was instantiated with
 411      *          {@code options} instead of an {@code optionType}.
 412      */
 413     public int getOptionType() {
 414         return optionType;
 415     }
 416 
 417     /**
 418      * Get the confirmation options.
 419      *
 420      * @return the list of confirmation options, or null if this
 421      *          {@code ConfirmationCallback} was instantiated with
 422      *          an {@code optionType} instead of {@code options}.
 423      */
 424     public String[] getOptions() {
 425         return options;
 426     }
 427 
 428     /**
 429      * Get the default option.
 430      *
 431      * @return the default option, represented as
 432      *          {@code YES}, {@code NO}, {@code OK} or
 433      *          {@code CANCEL} if an {@code optionType}
 434      *          was specified to the constructor of this
 435      *          {@code ConfirmationCallback}.
 436      *          Otherwise, this method returns the default option as
 437      *          an index into the
 438      *          {@code options} array specified to the constructor
 439      *          of this {@code ConfirmationCallback}.
 440      */
 441     public int getDefaultOption() {
 442         return defaultOption;
 443     }
 444 
 445     /**
 446      * Set the selected confirmation option.
 447      *
 448      * @param selection the selection represented as {@code YES},
 449      *          {@code NO}, {@code OK} or {@code CANCEL}
 450      *          if an {@code optionType} was specified to the constructor
 451      *          of this {@code ConfirmationCallback}.
 452      *          Otherwise, the selection represents the index into the
 453      *          {@code options} array specified to the constructor
 454      *          of this {@code ConfirmationCallback}.
 455      *
 456      * @see #getSelectedIndex
 457      */
 458     public void setSelectedIndex(int selection) {
 459         this.selection = selection;
 460     }
 461 
 462     /**
 463      * Get the selected confirmation option.
 464      *
 465      * @return the selected confirmation option represented as
 466      *          {@code YES}, {@code NO}, {@code OK} or
 467      *          {@code CANCEL} if an {@code optionType}
 468      *          was specified to the constructor of this
 469      *          {@code ConfirmationCallback}.
 470      *          Otherwise, this method returns the selected confirmation
 471      *          option as an index into the
 472      *          {@code options} array specified to the constructor
 473      *          of this {@code ConfirmationCallback}.
 474      *
 475      * @see #setSelectedIndex
 476      */
 477     public int getSelectedIndex() {
 478         return selection;
 479     }
 480 }