| /* |
| * $Id$ |
| * |
| * The Apache Software License, Version 1.1 |
| * |
| * |
| * Copyright (c) 2001-2003 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "Xalan" and "Apache Software Foundation" must |
| * not be used to endorse or promote products derived from this |
| * software without prior written permission. For written |
| * permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache", |
| * nor may "Apache" appear in their name, without prior written |
| * permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation and was |
| * originally based on software copyright (c) 2001, Sun |
| * Microsystems., http://www.sun.com. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| * |
| * @author G Todd Miller |
| * |
| */ |
| |
| package org.apache.xalan.xsltc.cmdline.getopt; |
| |
| import java.util.ArrayList; |
| import java.util.ListIterator; |
| import java.util.List; |
| |
| import org.apache.xalan.xsltc.cmdline.getopt.IllegalArgumentException; |
| import org.apache.xalan.xsltc.cmdline.getopt.MissingOptArgException; |
| 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. |
| */ |
| 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). |
| * @param none |
| * @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>'. |
| * @param none |
| * @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}. |
| * @params none |
| * @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 |
| 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. |
| // |
| 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 |
| |