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 getsubopt(3C)).
36 * <br>
37 * After constructing an instance of it, getNextSubOption() can be used
38 * to get the next suboption. getSubOptionArg() can be used to get the argument
39 * for that option.
40 *
41 */
42 public class GetSubOpt {
43
44 /**
45 * Delimiter between suboptions.
46 */
47 public final static String OPTION_DELIM = ",";
48
49 /**
50 * Delimiter between suboption and suboption argument.
51 */
52 public final static String VALUE_DELIM = "=";
53
54 /**
55 * List of suboptions.
56 */
57 protected String subOptions;
58
59 /**
60 * The length of the suboptions.
61 */
62 private final int subOptionsLen;
63
64 /**
65 * Current position with in suboptions.
66 */
67 protected int index;
68
69 /**
70 * Last suboption found.
71 */
72 protected String subOption;
73
74 /**
75 * Last suboption argument found.
76 */
77 protected String value;
78
79 /**
80 * Prepare a GetSubOpt object.
81 *
82 * @param subOptions
83 * String containing the list of suboptions. This value was most likely
84 * returned as an option argument by <i>GetOpt</i>.
85 */
86 public GetSubOpt(String subOptions) {
87 if (subOptions == null) {
88 this.subOptions = null;
89 } else {
90 this.subOptions = subOptions.trim();
91 }
92
93 index = 0;
94 subOptionsLen = subOptions.length();
95 }
96
97 /**
98 * Get the next suboption. The suboptions arguement is available from
99 * calling <i>getSubOptionArg()</i>.
100 *
101 * @return
102 * The next suboption.
103 * @exception IllegalArgumentException
104 * Thrown when no more suboptions remain.
105 */
106 public String getNextSubOption() throws IllegalArgumentException {
107
108 subOption = null;
109 value = null;
110
111 while (subOption == null || subOption.length() == 0) {
112
113 if (!hasMoreSubOptions()) {
114 String format =
115 ResourceStrings.getString("getsubopt_end_of_optionarg");
116 Object[] args = new Object[0];
117 String msg = MessageFormat.format(format, args);
118 throw new IllegalArgumentException(msg);
119 }
120
121 int optionIndex = subOptions.indexOf(OPTION_DELIM, index);
122 int valueIndex = subOptions.indexOf(VALUE_DELIM, index);
123
124 if (optionIndex == -1 && valueIndex == -1) {
125 // Last suboption and no value.
126 subOption = subOptions.substring(index);
127 index = subOptionsLen;
128 } else if (valueIndex == -1 ||
129 (optionIndex != -1 && optionIndex < valueIndex)) {
130 // Suboption has no value.
131 subOption = subOptions.substring(index, optionIndex);
132 index = optionIndex + OPTION_DELIM.length();
133 } else {
134 // Suboption with value.
135 subOption = subOptions.substring(index, valueIndex);
136 index = valueIndex + VALUE_DELIM.length();
137
138 boolean quoted = false;
139 int endIndex;
140
141 if (index < subOptionsLen &&
142 (subOptions.charAt(index) == '\"' ||
143 subOptions.charAt(index) == '\'')) {
144 // Value is quoted.
145 endIndex =
146 subOptions.indexOf(subOptions.charAt(index), index + 1);
147
148 // Missing close quote.
149 if (endIndex == -1) {
150 String format =
151 ResourceStrings.getString(
152 "getsubopt_missing_close_quote");
153 Object[] args = new Object[1];
154 args[0] = subOption;
155 String msg = MessageFormat.format(format, args);
156 throw new IllegalArgumentException(msg);
157 }
158
159 quoted = true;
160 index++;
161 } else {
162 // Value is not quoted.
163 endIndex = subOptions.indexOf(OPTION_DELIM, index);
164
165 if (endIndex == -1) {
166 endIndex = subOptionsLen;
167 }
168 }
169
170 value = subOptions.substring(index, endIndex);
171 index = endIndex;
172
173 // Skip closing quote.
174 if (quoted) {
175 index++;
176 }
177
178 /*
179 * Ensure that either the end of the suboptions has been
180 * reached or the next suboption is ready for parsing. For
181 * example, quoted values must not contain characters between
182 * the closing quote and OPTION_DELIM.
183 */
184 if (optionIndex >= 0) {
185 if (index < subOptionsLen &&
186 !subOptions.startsWith(OPTION_DELIM, index)) {
187 String format =
188 ResourceStrings.getString(
189 "getsubopt_malformed_value");
190 Object[] args = new Object[1];
191 args[0] = subOption;
192 String msg = MessageFormat.format(format, args);
193 throw new IllegalArgumentException(msg);
194 }
195
196 index += OPTION_DELIM.length();
197 }
198 }
199 }
200
201 return subOption;
202 }
203
204 /**
205 * Indicates whether more suboptions exist.
206 *
207 * @return
208 * True if at least one more suboption exists, otherwise false.
209 */
210 public boolean hasMoreSubOptions() throws IllegalArgumentException {
211 if (subOptions == null) {
212 return false;
213 }
214
215 // Skip over leading OPTION_DELIMs.
216 while (index < subOptionsLen &&
217 subOptions.indexOf(OPTION_DELIM, index) == index) {
218 index += OPTION_DELIM.length();
219 }
220
221 /*
222 * Ensure that there really is a suboption present. If a
223 * VALUE_DELIM has been found the suboption string is missing.
224 */
225 if (index < subOptionsLen &&
226 subOptions.indexOf(VALUE_DELIM, index) == index) {
227 String format =
228 ResourceStrings.getString(
229 "getsubopt_value_without_suboption");
230 Object[] args = new Object[0];
231 String msg = MessageFormat.format(format, args);
232 throw new IllegalArgumentException(msg);
233 }
234
235 return (index < subOptionsLen);
236 }
237
238 /**
239 * Get the current suboptions argument, or null if no argument is present.
240 *
241 * @return
242 * String containing the current suboptions argument, or null if the
243 * no argument is present.
244 */
245 public String getSubOptionArg() {
246 return value;
247 }
248 }
249