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 }