1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Copyright 2001-2004 The Apache Software Foundation. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 /* 21 * $Id: GetOpt.java,v 1.2.4.1 2005/08/31 11:46:04 pvedula Exp $ 22 */ 23 24 package com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt; 25 26 import java.util.ArrayList; 27 import java.util.List; 28 import java.util.ListIterator; 29 30 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; 31 32 33 /** 34 * GetOpt is a Java equivalent to the C getopt() library function 35 * discussed in man page getopt(3C). It provides command line 36 * parsing for Java applications. It supports the most rules of the 37 * command line standard (see man page intro(1)) including stacked 38 * options such as '-sxm' (which is equivalent to -s -x -m); it 39 * handles special '--' option that signifies the end of options. 40 * Additionally this implementation of getopt will check for 41 * mandatory arguments to options such as in the case of 42 * '-d <file>' it will throw a MissingOptArgException if the 43 * option argument '<file>' is not included on the commandline. 44 * getopt(3C) does not check for this. 45 * @author G Todd Miller 46 */ 47 public class GetOpt{ 48 public GetOpt(String[] args, String optString){ 49 theOptions = new ArrayList(); 50 int currOptIndex = 0; 51 theCmdArgs = new ArrayList(); 52 theOptionMatcher = new OptionMatcher(optString); 53 // fill in the options list 54 for(int i=0; i<args.length; i++){ 55 String token = args[i]; 56 int tokenLength = token.length(); 57 if(token.equals("--")){ // end of opts 58 currOptIndex = i+1; // set index of first operand 59 break; // end of options 60 } 61 else if(token.startsWith("-") && tokenLength == 2){ 62 // simple option token such as '-s' found 63 theOptions.add(new Option(token.charAt(1))); 64 } 65 else if(token.startsWith("-") && tokenLength > 2){ 66 // stacked options found, such as '-shm' 67 // iterate thru the tokens after the dash and 68 // add them to theOptions list 69 for(int j=1; j<tokenLength; j++){ 70 theOptions.add(new Option(token.charAt(j))); 71 } 72 } 73 else if(!token.startsWith("-")){ 74 // case 1- there are not options stored yet therefore 75 // this must be an command argument, not an option argument 76 if(theOptions.size() == 0){ 77 currOptIndex = i; 78 break; // stop processing options 79 } 80 else { 81 // case 2- 82 // there are options stored, check to see if 83 // this arg belong to the last arg stored 84 int indexoflast=0; 85 indexoflast = theOptions.size()-1; 86 Option op = (Option)theOptions.get(indexoflast); 87 char opLetter = op.getArgLetter(); 88 if(!op.hasArg() && theOptionMatcher.hasArg(opLetter)){ 89 op.setArg(token); 90 } 91 else{ 92 // case 3 - 93 // the last option stored does not take 94 // an argument, so again, this argument 95 // must be a command argument, not 96 // an option argument 97 currOptIndex = i; 98 break; // end of options 99 } 100 } 101 }// end option does not start with "-" 102 } // end for args loop 103 104 // attach an iterator to list of options 105 theOptionsIterator = theOptions.listIterator(); 106 107 // options are done, now fill out cmd arg list with remaining args 108 for(int i=currOptIndex; i<args.length; i++){ 109 String token = args[i]; 110 theCmdArgs.add(token); 111 } 112 } 113 114 115 /** 116 * debugging routine to print out all options collected 117 */ 118 public void printOptions(){ 119 for(ListIterator it=theOptions.listIterator(); it.hasNext();){ 120 Option opt = (Option)it.next(); 121 System.out.print("OPT =" + opt.getArgLetter()); 122 String arg = opt.getArgument(); 123 if(arg != null){ 124 System.out.print(" " + arg); 125 } 126 System.out.println(); 127 } 128 } 129 130 /** 131 * gets the next option found in the commandline. Distinguishes 132 * between two bad cases, one case is when an illegal option 133 * is found, and then other case is when an option takes an 134 * argument but no argument was found for that option. 135 * If the option found was not declared in the optString, then 136 * an IllegalArgumentException will be thrown (case 1). 137 * If the next option found has been declared to take an argument, 138 * and no such argument exists, then a MissingOptArgException 139 * is thrown (case 2). 140 * @param none 141 * @return int - the next option found. 142 * @throws IllegalArgumentException, MissingOptArgException. 143 */ 144 public int getNextOption() throws IllegalArgumentException, 145 MissingOptArgException 146 { 147 int retval = -1; 148 if(theOptionsIterator.hasNext()){ 149 theCurrentOption = (Option)theOptionsIterator.next(); 150 char c = theCurrentOption.getArgLetter(); 151 boolean shouldHaveArg = theOptionMatcher.hasArg(c); 152 String arg = theCurrentOption.getArgument(); 153 if(!theOptionMatcher.match(c)) { 154 ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_CMDLINE_OPTION_ERR, 155 new Character(c)); 156 throw (new IllegalArgumentException(msg.toString())); 157 } 158 else if(shouldHaveArg && (arg == null)) { 159 ErrorMsg msg = new ErrorMsg(ErrorMsg.CMDLINE_OPT_MISSING_ARG_ERR, 160 new Character(c)); 161 throw (new MissingOptArgException(msg.toString())); 162 } 163 retval = c; 164 } 165 return retval; 166 } 167 168 /** 169 * gets the argument for the current parsed option. For example, 170 * in case of '-d <file>', if current option parsed is 'd' then 171 * getOptionArg() would return '<file>'. 172 * @return String - argument for current parsed option. 173 * @param none 174 */ 175 public String getOptionArg(){ 176 String retval = null; 177 String tmp = theCurrentOption.getArgument(); 178 char c = theCurrentOption.getArgLetter(); 179 if(theOptionMatcher.hasArg(c)){ 180 retval = tmp; 181 } 182 return retval; 183 } 184 185 /** 186 * gets list of the commandline arguments. For example, in command 187 * such as 'cmd -s -d file file2 file3 file4' with the usage 188 * 'cmd [-s] [-d <file>] <file>...', getCmdArgs() would return 189 * the list {file2, file3, file4}. 190 * @return String[] - list of command arguments that may appear 191 * after options and option arguments. 192 * @params none 193 */ 194 public String[] getCmdArgs(){ 195 String[] retval = new String[theCmdArgs.size()]; 196 int i=0; 197 for(ListIterator it=theCmdArgs.listIterator(); it.hasNext();){ 198 retval[i++] = (String)it.next(); 199 } 200 return retval; 201 } 202 203 204 private Option theCurrentOption = null; 205 private ListIterator theOptionsIterator; 206 private List theOptions = null; 207 private List theCmdArgs = null; 208 private OptionMatcher theOptionMatcher = null; 209 210 /////////////////////////////////////////////////////////// 211 // 212 // Inner Classes 213 // 214 /////////////////////////////////////////////////////////// 215 216 // inner class to model an option 217 class Option{ 218 private char theArgLetter; 219 private String theArgument = null; 220 public Option(char argLetter) { theArgLetter = argLetter; } 221 public void setArg(String arg) { 222 theArgument = arg; 223 } 224 public boolean hasArg() { return (theArgument != null); } 225 public char getArgLetter() { return theArgLetter; } 226 public String getArgument() { return theArgument; } 227 } // end class Option 228 229 230 // inner class to query optString for a possible option match, 231 // and whether or not a given legal option takes an argument. 232 // 233 class OptionMatcher{ 234 public OptionMatcher(String optString){ 235 theOptString = optString; 236 } 237 public boolean match(char c){ 238 boolean retval = false; 239 if(theOptString.indexOf(c) != -1){ 240 retval = true; 241 } 242 return retval; 243 } 244 public boolean hasArg(char c){ 245 boolean retval = false; 246 int index = theOptString.indexOf(c)+1; 247 if (index == theOptString.length()){ 248 // reached end of theOptString 249 retval = false; 250 } 251 else if(theOptString.charAt(index) == ':'){ 252 retval = true; 253 } 254 return retval; 255 } 256 private String theOptString = null; 257 } // end class OptionMatcher 258 }// end class GetOpt