| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| /* |
| * $Id$ |
| */ |
| |
| package org.apache.xalan.xsltc.cmdline.getopt; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.ListIterator; |
| |
| import org.apache.xalan.xsltc.compiler.util.ErrorMsg; |
| |
| |
| /** |
| * GetOpt is a Java equivalent to the C getopt() library function |
| * discussed in man page getopt(3C). It provides command line |
| * parsing for Java applications. It supports the most rules of the |
| * command line standard (see man page intro(1)) including stacked |
| * options such as '-sxm' (which is equivalent to -s -x -m); it |
| * handles special '--' option that signifies the end of options. |
| * Additionally this implementation of getopt will check for |
| * mandatory arguments to options such as in the case of |
| * '-d <file>' it will throw a MissingOptArgException if the |
| * option argument '<file>' is not included on the commandline. |
| * getopt(3C) does not check for this. |
| * @author G Todd Miller |
| */ |
| public class GetOpt{ |
| public GetOpt(String[] args, String optString){ |
| theOptions = new ArrayList(); |
| int currOptIndex = 0; |
| theCmdArgs = new ArrayList(); |
| theOptionMatcher = new OptionMatcher(optString); |
| // fill in the options list |
| for(int i=0; i<args.length; i++){ |
| String token = args[i]; |
| int tokenLength = token.length(); |
| if(token.equals("--")){ // end of opts |
| currOptIndex = i+1; // set index of first operand |
| break; // end of options |
| } |
| else if(token.startsWith("-") && tokenLength == 2){ |
| // simple option token such as '-s' found |
| theOptions.add(new Option(token.charAt(1))); |
| } |
| else if(token.startsWith("-") && tokenLength > 2){ |
| // stacked options found, such as '-shm' |
| // iterate thru the tokens after the dash and |
| // add them to theOptions list |
| for(int j=1; j<tokenLength; j++){ |
| theOptions.add(new Option(token.charAt(j))); |
| } |
| } |
| else if(!token.startsWith("-")){ |
| // case 1- there are not options stored yet therefore |
| // this must be an command argument, not an option argument |
| if(theOptions.size() == 0){ |
| currOptIndex = i; |
| break; // stop processing options |
| } |
| else { |
| // case 2- |
| // there are options stored, check to see if |
| // this arg belong to the last arg stored |
| int indexoflast=0; |
| indexoflast = theOptions.size()-1; |
| Option op = (Option)theOptions.get(indexoflast); |
| char opLetter = op.getArgLetter(); |
| if(!op.hasArg() && theOptionMatcher.hasArg(opLetter)){ |
| op.setArg(token); |
| } |
| else{ |
| // case 3 - |
| // the last option stored does not take |
| // an argument, so again, this argument |
| // must be a command argument, not |
| // an option argument |
| currOptIndex = i; |
| break; // end of options |
| } |
| } |
| }// end option does not start with "-" |
| } // end for args loop |
| |
| // attach an iterator to list of options |
| theOptionsIterator = theOptions.listIterator(); |
| |
| // options are done, now fill out cmd arg list with remaining args |
| for(int i=currOptIndex; i<args.length; i++){ |
| String token = args[i]; |
| theCmdArgs.add(token); |
| } |
| } |
| |
| |
| /** |
| * debugging routine to print out all options collected |
| */ |
| public void printOptions(){ |
| for(ListIterator it=theOptions.listIterator(); it.hasNext();){ |
| Option opt = (Option)it.next(); |
| System.out.print("OPT =" + opt.getArgLetter()); |
| String arg = opt.getArgument(); |
| if(arg != null){ |
| System.out.print(" " + arg); |
| } |
| System.out.println(); |
| } |
| } |
| |
| /** |
| * gets the next option found in the commandline. Distinguishes |
| * between two bad cases, one case is when an illegal option |
| * is found, and then other case is when an option takes an |
| * argument but no argument was found for that option. |
| * If the option found was not declared in the optString, then |
| * an IllegalArgumentException will be thrown (case 1). |
| * If the next option found has been declared to take an argument, |
| * and no such argument exists, then a MissingOptArgException |
| * is thrown (case 2). |
| * @return int - the next option found. |
| * @throws IllegalArgumentException, MissingOptArgException. |
| */ |
| public int getNextOption() throws IllegalArgumentException, |
| MissingOptArgException |
| { |
| int retval = -1; |
| if(theOptionsIterator.hasNext()){ |
| theCurrentOption = (Option)theOptionsIterator.next(); |
| char c = theCurrentOption.getArgLetter(); |
| boolean shouldHaveArg = theOptionMatcher.hasArg(c); |
| String arg = theCurrentOption.getArgument(); |
| if(!theOptionMatcher.match(c)) { |
| ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_CMDLINE_OPTION_ERR, |
| new Character(c)); |
| throw (new IllegalArgumentException(msg.toString())); |
| } |
| else if(shouldHaveArg && (arg == null)) { |
| ErrorMsg msg = new ErrorMsg(ErrorMsg.CMDLINE_OPT_MISSING_ARG_ERR, |
| new Character(c)); |
| throw (new MissingOptArgException(msg.toString())); |
| } |
| retval = c; |
| } |
| return retval; |
| } |
| |
| /** |
| * gets the argument for the current parsed option. For example, |
| * in case of '-d <file>', if current option parsed is 'd' then |
| * getOptionArg() would return '<file>'. |
| * @return String - argument for current parsed option. |
| */ |
| public String getOptionArg(){ |
| String retval = null; |
| String tmp = theCurrentOption.getArgument(); |
| char c = theCurrentOption.getArgLetter(); |
| if(theOptionMatcher.hasArg(c)){ |
| retval = tmp; |
| } |
| return retval; |
| } |
| |
| /** |
| * gets list of the commandline arguments. For example, in command |
| * such as 'cmd -s -d file file2 file3 file4' with the usage |
| * 'cmd [-s] [-d <file>] <file>...', getCmdArgs() would return |
| * the list {file2, file3, file4}. |
| * @return String[] - list of command arguments that may appear |
| * after options and option arguments. |
| */ |
| public String[] getCmdArgs(){ |
| String[] retval = new String[theCmdArgs.size()]; |
| int i=0; |
| for(ListIterator it=theCmdArgs.listIterator(); it.hasNext();){ |
| retval[i++] = (String)it.next(); |
| } |
| return retval; |
| } |
| |
| |
| private Option theCurrentOption = null; |
| private ListIterator theOptionsIterator; |
| private List theOptions = null; |
| private List theCmdArgs = null; |
| private OptionMatcher theOptionMatcher = null; |
| |
| /////////////////////////////////////////////////////////// |
| // |
| // Inner Classes |
| // |
| /////////////////////////////////////////////////////////// |
| |
| // inner class to model an option |
| static class Option{ |
| private char theArgLetter; |
| private String theArgument = null; |
| public Option(char argLetter) { theArgLetter = argLetter; } |
| public void setArg(String arg) { |
| theArgument = arg; |
| } |
| public boolean hasArg() { return (theArgument != null); } |
| public char getArgLetter() { return theArgLetter; } |
| public String getArgument() { return theArgument; } |
| } // end class Option |
| |
| |
| // inner class to query optString for a possible option match, |
| // and whether or not a given legal option takes an argument. |
| // |
| static class OptionMatcher{ |
| public OptionMatcher(String optString){ |
| theOptString = optString; |
| } |
| public boolean match(char c){ |
| boolean retval = false; |
| if(theOptString.indexOf(c) != -1){ |
| retval = true; |
| } |
| return retval; |
| } |
| public boolean hasArg(char c){ |
| boolean retval = false; |
| int index = theOptString.indexOf(c)+1; |
| if (index == theOptString.length()){ |
| // reached end of theOptString |
| retval = false; |
| } |
| else if(theOptString.charAt(index) == ':'){ |
| retval = true; |
| } |
| return retval; |
| } |
| private String theOptString = null; |
| } // end class OptionMatcher |
| }// end class GetOpt |
| |