1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * ident        "%Z%%M% %I%     %E% SMI"
  24  *
  25  * Copyright 1998-2002 Sun Microsystems, Inc.  All rights reserved.
  26  * Use is subject to license terms.
  27  */
  28 package com.sun.dhcpmgr.cli.common;
  29 
  30 import java.lang.IllegalArgumentException;
  31 import java.text.MessageFormat;
  32 
  33 /**
  34  * This class provides the functionality for parsing command line
  35  * arguments (similar to getopt(3C)).
  36  * After constructing an instance of it, getNextOption() can be used
  37  * to get the next option. getOptionArg() can be used to get the argument for
  38  * that option. getNextOptionIndex() returns how many arguments are already
  39  * processed from the arguments list.
  40  *
  41  * This code was "borrowed" from the Viper project. We have our own copy of
  42  * this code, because the Viper project has deprecated their class and we
  43  * have had to modify the original code.
  44  */
  45 public class GetOpt {
  46     protected int       optind          = 0;
  47     protected String    optarg          = null;
  48     protected String    argv[]          = null;
  49     protected int       argc            = 0;
  50     protected String    optionString    = null;
  51 
  52     // e.g in -v (- is in 0th position)
  53     //
  54     int MINUS_POSITION = 0; 
  55 
  56     // e.g. in -v (v is in 1st position )
  57     //
  58     int OPTION_POSITION = 1;
  59 
  60     // e.g. in -vGoldrush (G is in 2nd position )
  61     //
  62     int AFTER_OPTION_POSITION = 2;
  63 
  64     /**
  65      * Constructor
  66      * @parameter argv  -- Array of string arguments.
  67      * @parameter optionString --  contains the option letters that
  68      *            will be recognized;
  69      *            if a letter is followed by a colon,
  70      *            the option is expected to have  an  argument.
  71      *            if a letter is followed by a semi-colon,
  72      *            the argument to the letter is optional.
  73      * e.g. abdf:e
  74      *      legal arguments are a, b, d, f, e.
  75      *      f option requires a argument.
  76      */
  77     public GetOpt(String argv[], String optionString) {
  78         this.argv = argv;
  79         this.optionString = optionString;
  80         this.argc = argv.length;
  81     }
  82 
  83     /*
  84      * Returns the next valid option.
  85      * Throws an IllegalArgumentException
  86      *   a) if option is not valid or
  87      *   b) an option required an argument and is not provided
  88      * Returns -1 if no more options left.
  89      */
  90     public int getNextOption() throws IllegalArgumentException {
  91         char currentOption;
  92         optarg = null;
  93 
  94         // ------------------------------------------------
  95         // Find out if option exists
  96 
  97         if (optind >= argc || (argv[optind].length() < 2) ||
  98                 argv[optind].charAt(MINUS_POSITION) != '-') {
  99 
 100             return -1;
 101         }
 102 
 103         // ---------------------------------------------------
 104         // So see if it is a legal option
 105 
 106         currentOption = argv[optind].charAt(OPTION_POSITION);
 107 
 108         if (!isValidOption(currentOption)) {
 109             optind = optind + 1;
 110             String format = ResourceStrings.getString("getopt_illegal_option");
 111             Object[] args = new Object[1];
 112             args[0] = new Character((char)currentOption);
 113             String msg = MessageFormat.format(format, args);
 114             throw new IllegalArgumentException(msg);
 115         }
 116 
 117         // ------------------------------------------------------------
 118         // We have a legal option now, find out if it expected to have optarg.
 119 
 120         if (isOptionArgAllowedByOption(currentOption) &&
 121                 OPTION_POSITION == 1) {
 122 
 123             // -------------------------------------
 124             // Case when optarg is given with the option itself,
 125             // like -hlastgas.east. Then extract the optarg out.
 126 
 127             if (argv[optind].length() != 2) {
 128                 optarg = argv[optind].substring(AFTER_OPTION_POSITION);
 129                 optind++;
 130             }
 131             // ------------------------------------------
 132             // Case when optarg is not provided, return error if it was
 133             // mandatory
 134 
 135             else if (optind+1 >= argc) {
 136                 optind++;
 137                 if (isOptionArgMandatoryByOption(currentOption)) {
 138                     String format =
 139                         ResourceStrings.getString("getopt_requires_argument");
 140                     Object[] args = new Object[1];
 141                     args[0] = new Character((char)currentOption);
 142                     String msg = MessageFormat.format(format, args);
 143                     throw new IllegalArgumentException(msg);
 144                 }
 145             }
 146             // ------------------------------------------------
 147             // Case when there is a argument that could have been used
 148             // as a optarg, but actually it is just another option.
 149 
 150             else if ((argv[optind+1].length() > MINUS_POSITION) &&
 151                    (argv[optind+1].charAt(MINUS_POSITION) == '-') &&
 152                    (isValidOption(argv[optind+1].charAt(OPTION_POSITION)))) {
 153                 optind++;
 154                 if (isOptionArgMandatoryByOption(currentOption)) {
 155                     String format =
 156                         ResourceStrings.getString("getopt_requires_argument");
 157                     Object[] args = new Object[1];
 158                     args[0] = new Character((char)currentOption);
 159                     String msg = MessageFormat.format(format, args);
 160                     throw new IllegalArgumentException(msg);
 161                 }
 162             }
 163 
 164             // --------------------------------------------
 165             // Finally the good case
 166 
 167             else {
 168                 optarg = argv[++optind];
 169                 optind++;
 170             }
 171 
 172             OPTION_POSITION = 1;
 173 
 174         } else if (isOptionArgMandatoryByOption(currentOption)) {
 175             String format = ResourceStrings.getString("getopt_cannot_group");
 176             Object[] args = new Object[1];
 177             args[0] = new Character((char)currentOption);
 178             String msg = MessageFormat.format(format, args);
 179             throw new IllegalArgumentException(msg);
 180         } else if (argv[optind].length() == OPTION_POSITION + 1) {
 181             OPTION_POSITION = 1;
 182             optind++;
 183         } else {        // illegal argument supplied for option
 184             OPTION_POSITION++;
 185         }
 186         return currentOption;
 187     }
 188 
 189     /**
 190      * Returns the argument for the option being handled.
 191      */
 192     public String getOptionArg() {
 193         return optarg;
 194     }
 195 
 196     /**
 197      * Returns true if option is a valid option
 198      */
 199     private boolean isValidOption(char c) {
 200         if ((c == ':') || (optionString.indexOf(c) == -1)) {
 201             return false;
 202         } else {
 203             return true;
 204         }
 205     }
 206 
 207     /**
 208      * Returns true if option provided needs a argument.
 209      * throws exception if option is not a valid option at first place.
 210      */
 211     private boolean isOptionArgMandatoryByOption(char option) {
 212         int x = option;
 213         if (isValidOption(option)
 214            && (optionString.length() > optionString.indexOf(option) + 1)
 215            && (optionString.charAt(optionString.indexOf(option) + 1) == ':'))
 216             return true;
 217         else
 218             return false;
 219     }
 220 
 221     /**
 222      * Returns how many arguments are already processed by the getNextOption()
 223      * function. The other way to look at it is what argument is going to be
 224      * processed by getNextOption() method next.
 225      */
 226     public int getNextOptionIndex() {
 227         return optind;
 228     }
 229 
 230     /**
 231      * Returns true if option provided allows a argument.
 232      * throws exception if option is not a valid option at first place.
 233      */
 234     private boolean isOptionArgAllowedByOption(char option) {
 235         int x = option;
 236         if (isValidOption(option)
 237            && (optionString.length() > optionString.indexOf(option) + 1)
 238            && ((optionString.charAt(optionString.indexOf(option) + 1) == ':') ||
 239                 (optionString.charAt(optionString.indexOf(option) + 1) == ';')))
 240             return true;
 241         else
 242             return false;
 243     }
 244 }