Author: roxspring Date: Fri Jun 3 14:57:28 2005 New Revision: 179898 URL: http://svn.apache.org/viewcvs?rev=179898&view=rev Log: Added the old Avalon Excalibur CLI package Submitted by: Sebb Issue: 34672
Added: jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/ jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/AbstractParserControl.java jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLArgsParser.java jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLOption.java jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLOptionDescriptor.java jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLUtil.java jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/ParserControl.java jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/Token.java jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/package.html jakarta/commons/proper/cli/trunk/src/test/org/apache/commons/cli/avalon/ jakarta/commons/proper/cli/trunk/src/test/org/apache/commons/cli/avalon/ClutilTestCase.java Added: jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/AbstractParserControl.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/AbstractParserControl.java?rev=179898&view=auto ============================================================================== --- jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/AbstractParserControl.java (added) +++ jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/AbstractParserControl.java Fri Jun 3 14:57:28 2005 @@ -0,0 +1,40 @@ +/* + * Copyright 2002-2005 The Apache Software Foundation + * Licensed 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. + */ +package org.apache.commons.cli.avalon; +//Renamed from org.apache.avalon.excalibur.cli + +/** + * Class to inherit from so when in future when new controls are added + * clients will no have to implement them. + * @version $Revision: 1.2 $ + * @see ParserControl + */ +public abstract class AbstractParserControl + implements ParserControl +{ + /** + * By default always continue parsing by returning false. + * + * @param lastOptionCode the code of last option parsed + * @return return true to halt, false to continue parsing + * @see ParserControl#isFinished(int) + */ + public boolean isFinished( int lastOptionCode ) + { + return false; + } +} Added: jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLArgsParser.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLArgsParser.java?rev=179898&view=auto ============================================================================== --- jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLArgsParser.java (added) +++ jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLArgsParser.java Fri Jun 3 14:57:28 2005 @@ -0,0 +1,810 @@ +/* + * Copyright 2002-2005 The Apache Software Foundation + * Licensed 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. + */ +package org.apache.commons.cli.avalon; +//Renamed from org.apache.avalon.excalibur.cli + +import java.text.ParseException; +import java.util.Hashtable; +import java.util.Vector; + +/** + * Parser for command line arguments. + * + * This parses command lines according to the standard (?) of + * GNU utilities. + * + * Note: This is still used in 1.1 libraries so do not add 1.2+ dependencies. + * + * Note that CLArgs uses a backing hashtable for the options index and so duplicate + * arguments are only returned by getArguments(). + * + * @version $Revision: 1.2 $ $Date: 2005/03/18 15:26:55 $ + * @see ParserControl + * @see CLOption + * @see CLOptionDescriptor + */ +public final class CLArgsParser +{ + //cached character == Integer.MAX_VALUE when invalid + private static final int INVALID = Integer.MAX_VALUE; + + private static final int STATE_NORMAL = 0; + private static final int STATE_REQUIRE_2ARGS = 1; + private static final int STATE_REQUIRE_ARG = 2; + private static final int STATE_OPTIONAL_ARG = 3; + private static final int STATE_NO_OPTIONS = 4; + private static final int STATE_OPTION_MODE = 5; + + // Values for creating tokens + private static final int TOKEN_SEPARATOR = 0; + private static final int TOKEN_STRING = 1; + + private static final char[] ARG_SEPARATORS = + new char[]{(char)0, '='}; + + private static final char[] NULL_SEPARATORS = + new char[]{(char)0}; + + private final CLOptionDescriptor[] m_optionDescriptors; + private final Vector m_options; + private Hashtable m_optionIndex; + private final ParserControl m_control; + + private String m_errorMessage; + private String[] m_unparsedArgs = new String[]{}; + + //variables used while parsing options. + private char m_ch; + private String[] m_args; + private boolean m_isLong; + private int m_argIndex; + private int m_stringIndex; + private int m_stringLength; + + private int m_lastChar = INVALID; + + private int m_lastOptionId; + private CLOption m_option; + private int m_state = STATE_NORMAL; + + /** + * Retrieve an array of arguments that have not been parsed + * due to the parser halting. + * + * @return an array of unparsed args + */ + public final String[] getUnparsedArgs() + { + return m_unparsedArgs; + } + + /** + * Retrieve a list of options that were parsed from command list. + * + * @return the list of options + */ + public final Vector getArguments() + { + //System.out.println( "Arguments: " + m_options ); + return m_options; + } + + /** + * Retrieve the [EMAIL PROTECTED] CLOption} with specified id, or + * <code>null</code> if no command line option is found. + * + * @param id the command line option id + * @return the [EMAIL PROTECTED] CLOption} with the specified id, or + * <code>null</code> if no CLOption is found. + * @see CLOption + */ + public final CLOption getArgumentById( final int id ) + { + return (CLOption)m_optionIndex.get( new Integer( id ) ); + } + + /** + * Retrieve the [EMAIL PROTECTED] CLOption} with specified name, or + * <code>null</code> if no command line option is found. + * + * @param name the command line option name + * @return the [EMAIL PROTECTED] CLOption} with the specified name, or + * <code>null</code> if no CLOption is found. + * @see CLOption + */ + public final CLOption getArgumentByName( final String name ) + { + return (CLOption)m_optionIndex.get( name ); + } + + /** + * Get Descriptor for option id. + * + * @param id the id + * @return the descriptor + */ + private final CLOptionDescriptor getDescriptorFor( final int id ) + { + for( int i = 0; i < m_optionDescriptors.length; i++ ) + { + if( m_optionDescriptors[i].getId() == id ) + { + return m_optionDescriptors[i]; + } + } + + return null; + } + + /** + * Retrieve a descriptor by name. + * + * @param name the name + * @return the descriptor + */ + private final CLOptionDescriptor getDescriptorFor( final String name ) + { + for( int i = 0; i < m_optionDescriptors.length; i++ ) + { + if( m_optionDescriptors[i].getName().equals( name ) ) + { + return m_optionDescriptors[i]; + } + } + + return null; + } + + /** + * Retrieve an error message that occured during parsing if one existed. + * + * @return the error string + */ + public final String getErrorString() + { + //System.out.println( "ErrorString: " + m_errorMessage ); + return m_errorMessage; + } + + /** + * Require state to be placed in for option. + * + * @param descriptor the Option Descriptor + * @return the state + */ + private final int getStateFor( final CLOptionDescriptor descriptor ) + { + final int flags = descriptor.getFlags(); + if( (flags & CLOptionDescriptor.ARGUMENTS_REQUIRED_2) == + CLOptionDescriptor.ARGUMENTS_REQUIRED_2 ) + { + return STATE_REQUIRE_2ARGS; + } + else if( (flags & CLOptionDescriptor.ARGUMENT_REQUIRED) == + CLOptionDescriptor.ARGUMENT_REQUIRED ) + { + return STATE_REQUIRE_ARG; + } + else if( (flags & CLOptionDescriptor.ARGUMENT_OPTIONAL) == + CLOptionDescriptor.ARGUMENT_OPTIONAL ) + { + return STATE_OPTIONAL_ARG; + } + else + { + return STATE_NORMAL; + } + } + + /** + * Create a parser that can deal with options and parses certain args. + * + * @param args the args, typically that passed to the + * <code>public static void main(String[] args)</code> method. + * @param optionDescriptors the option descriptors + * @param control the parser control used determine behaviour of parser + */ + public CLArgsParser( final String[] args, + final CLOptionDescriptor[] optionDescriptors, + final ParserControl control ) + { + m_optionDescriptors = optionDescriptors; + m_control = control; + m_options = new Vector(); + m_args = args; + + try + { + parse(); + checkIncompatibilities( m_options ); + buildOptionIndex(); + } + catch( final ParseException pe ) + { + m_errorMessage = pe.getMessage(); + } + + //System.out.println( "Built : " + m_options ); + //System.out.println( "From : " + Arrays.asList( args ) ); + } + + /** + * Check for duplicates of an option. + * It is an error to have duplicates unless appropriate flags is set in descriptor. + * + * @param arguments the arguments + */ + private final void checkIncompatibilities( final Vector arguments ) + throws ParseException + { + final int size = arguments.size(); + + for( int i = 0; i < size; i++ ) + { + final CLOption option = (CLOption)arguments.elementAt( i ); + final int id = option.getDescriptor().getId(); + final CLOptionDescriptor descriptor = getDescriptorFor( id ); + + //this occurs when id == 0 and user has not supplied a descriptor + //for arguments + if( null == descriptor ) + { + continue; + } + + final int[] incompatible = descriptor.getIncompatible(); + + checkIncompatible( arguments, incompatible, i ); + } + } + + private final void checkIncompatible( final Vector arguments, + final int[] incompatible, + final int original ) + throws ParseException + { + final int size = arguments.size(); + + for( int i = 0; i < size; i++ ) + { + if( original == i ) + { + continue; + } + + final CLOption option = (CLOption)arguments.elementAt( i ); + final int id = option.getDescriptor().getId(); + + for( int j = 0; j < incompatible.length; j++ ) + { + if( id == incompatible[j] ) + { + final CLOption originalOption = (CLOption)arguments.elementAt( original ); + final int originalId = originalOption.getDescriptor().getId(); + + String message = null; + + if( id == originalId ) + { + message = + "Duplicate options for " + describeDualOption( originalId ) + + " found."; + } + else + { + message = "Incompatible options -" + + describeDualOption( id ) + " and " + + describeDualOption( originalId ) + " found."; + } + throw new ParseException( message, 0 ); + } + } + } + } + + private final String describeDualOption( final int id ) + { + final CLOptionDescriptor descriptor = getDescriptorFor( id ); + if( null == descriptor ) + { + return "<parameter>"; + } + else + { + final StringBuffer sb = new StringBuffer(); + boolean hasCharOption = false; + + if( Character.isLetter( (char)id ) ) + { + sb.append( '-' ); + sb.append( (char)id ); + hasCharOption = true; + } + + final String longOption = descriptor.getName(); + if( null != longOption ) + { + if( hasCharOption ) + { + sb.append( '/' ); + } + sb.append( "--" ); + sb.append( longOption ); + } + + return sb.toString(); + } + } + + /** + * Create a parser that deals with options and parses certain args. + * + * @param args the args + * @param optionDescriptors the option descriptors + */ + public CLArgsParser( final String[] args, + final CLOptionDescriptor[] optionDescriptors ) + { + this( args, optionDescriptors, null ); + } + + /** + * Create a string array that is subset of input array. + * The sub-array should start at array entry indicated by index. That array element + * should only include characters from charIndex onwards. + * + * @param array the original array + * @param index the cut-point in array + * @param charIndex the cut-point in element of array + * @return the result array + */ + private final String[] subArray( final String[] array, + final int index, + final int charIndex ) + { + final int remaining = array.length - index; + final String[] result = new String[remaining]; + + if( remaining > 1 ) + { + System.arraycopy( array, index + 1, result, 1, remaining - 1 ); + } + + result[0] = array[index].substring( charIndex - 1 ); + + return result; + } + + /** + * Actually parse arguments + */ + private final void parse() + throws ParseException + { + if( 0 == m_args.length ) + { + return; + } + + m_stringLength = m_args[m_argIndex].length(); + + //ch = peekAtChar(); + + while( true ) + { + m_ch = peekAtChar(); + + //System.out.println( "Pre State=" + m_state ); + //System.out.println( "Pre Char=" + (char)ch + "/" + (int)ch ); + + if( m_argIndex >= m_args.length ) + { + break; + } + + if( null != m_control && m_control.isFinished( m_lastOptionId ) ) + { + //this may need mangling due to peeks + m_unparsedArgs = subArray( m_args, m_argIndex, m_stringIndex ); + return; + } + + //System.out.println( "State=" + m_state ); + //System.out.println( "Char=" + (char)ch + "/" + (int)ch ); + + if( STATE_OPTION_MODE == m_state ) + { + //if get to an arg barrier then return to normal mode + //else continue accumulating options + if( 0 == m_ch ) + { + getChar(); //strip the null + m_state = STATE_NORMAL; + } + else + { + parseShortOption(); + } + } + else if( STATE_NORMAL == m_state ) + { + parseNormal(); + } + else if( STATE_NO_OPTIONS == m_state ) + { + //should never get to here when stringIndex != 0 + addOption( new CLOption( m_args[m_argIndex++] ) ); + } + else if( STATE_OPTIONAL_ARG == m_state && m_isLong && m_ch != 0) + { + m_state = STATE_NORMAL; + addOption( m_option ); + } + else + { + parseArguments(); + } + } + + if( m_option != null ) + { + if( STATE_OPTIONAL_ARG == m_state ) + { + m_options.addElement( m_option ); + } + else if( STATE_REQUIRE_ARG == m_state ) + { + final CLOptionDescriptor descriptor = getDescriptorFor( + m_option.getDescriptor().getId() ); + final String message = + "Missing argument to option " + getOptionDescription( descriptor ); + throw new ParseException( message, 0 ); + } + else if( STATE_REQUIRE_2ARGS == m_state ) + { + if( 1 == m_option.getArgumentCount() ) + { + m_option.addArgument( "" ); + m_options.addElement( m_option ); + } + else + { + final CLOptionDescriptor descriptor = getDescriptorFor( + m_option.getDescriptor().getId() ); + final String message = + "Missing argument to option " + getOptionDescription( descriptor ); + throw new ParseException( message, 0 ); + } + } + else + { + throw new ParseException( "IllegalState " + m_state + ": " + m_option, 0 ); + } + } + } + + private final String getOptionDescription( final CLOptionDescriptor descriptor ) + { + if( m_isLong ) + { + return "--" + descriptor.getName(); + } + else + { + return "-" + (char)descriptor.getId(); + } + } + + private final char peekAtChar() + { + if( INVALID == m_lastChar ) + { + m_lastChar = readChar(); + } + return (char)m_lastChar; + } + + private final char getChar() + { + if( INVALID != m_lastChar ) + { + final char result = (char)m_lastChar; + m_lastChar = INVALID; + return result; + } + else + { + return readChar(); + } + } + + private final char readChar() + { + if( m_stringIndex >= m_stringLength ) + { + m_argIndex++; + m_stringIndex = 0; + + if( m_argIndex < m_args.length ) + { + m_stringLength = m_args[m_argIndex].length(); + } + else + { + m_stringLength = 0; + } + + return 0; + } + + if( m_argIndex >= m_args.length ) + { + return 0; + } + + return m_args[m_argIndex].charAt( m_stringIndex++ ); + } + + private final Token nextToken( final char[] separators ) + { + m_ch = getChar(); + + if( isSeparator( m_ch, separators ) ) + { + m_ch = getChar(); + return new Token( TOKEN_SEPARATOR, null ); + } + + final StringBuffer sb = new StringBuffer(); + + do + { + sb.append( m_ch ); + m_ch = getChar(); + } + while( !isSeparator( m_ch, separators ) ); + + return new Token( TOKEN_STRING, sb.toString() ); + } + + private final boolean isSeparator( final char ch, final char[] separators ) + { + for( int i = 0; i < separators.length; i++ ) + { + if( ch == separators[i] ) + { + return true; + } + } + + return false; + } + + private final void addOption( final CLOption option ) + { + m_options.addElement( option ); + m_lastOptionId = option.getDescriptor().getId(); + m_option = null; + } + + private final void parseOption( final CLOptionDescriptor descriptor, + final String optionString ) + throws ParseException + { + if( null == descriptor ) + { + throw new ParseException( "Unknown option " + optionString, 0 ); + } + + m_state = getStateFor( descriptor ); + m_option = new CLOption( descriptor ); + + if( STATE_NORMAL == m_state ) + { + addOption( m_option ); + } + } + + private final void parseShortOption() + throws ParseException + { + m_ch = getChar(); + final CLOptionDescriptor descriptor = getDescriptorFor( m_ch ); + m_isLong = false; + parseOption( descriptor, "-" + m_ch ); + + if( STATE_NORMAL == m_state ) + { + m_state = STATE_OPTION_MODE; + } + } + + private final void parseArguments() + throws ParseException + { + if( STATE_REQUIRE_ARG == m_state ) + { + if( '=' == m_ch || 0 == m_ch ) + { + getChar(); + } + + final Token token = nextToken( NULL_SEPARATORS ); + m_option.addArgument( token.getValue() ); + + addOption( m_option ); + m_state = STATE_NORMAL; + } + else if( STATE_OPTIONAL_ARG == m_state ) + { + if( '-' == m_ch || 0 == m_ch ) + { + getChar(); //consume stray character + addOption( m_option ); + m_state = STATE_NORMAL; + return; + } + + if( '=' == m_ch ) + { + getChar(); + } + + final Token token = nextToken( NULL_SEPARATORS ); + m_option.addArgument( token.getValue() ); + + addOption( m_option ); + m_state = STATE_NORMAL; + } + else if( STATE_REQUIRE_2ARGS == m_state ) + { + if( 0 == m_option.getArgumentCount() ) + { + /* + * Fix bug: -D arg1=arg2 was causing parse error; however --define arg1=arg2 is OK + * This seems to be because the parser skips the terminator for the long options, + * but was not doing so for the short options. + */ + if (!m_isLong){ + if (0 == peekAtChar()){ + getChar(); + } + } + final Token token = nextToken( ARG_SEPARATORS ); + + if( TOKEN_SEPARATOR == token.getType() ) + { + final CLOptionDescriptor descriptor = getDescriptorFor( + m_option.getDescriptor().getId() ); + final String message = + "Unable to parse first argument for option " + + getOptionDescription( descriptor ); + throw new ParseException( message, 0 ); + } + else + { + m_option.addArgument( token.getValue() ); + } + // Are we about to start a new option? + if (0 == m_ch && '-' == peekAtChar()){ + // Yes, so the second argument is missing + m_option.addArgument( "" ); + m_options.addElement( m_option ); + m_state = STATE_NORMAL; + } + } + else //2nd argument + { + final StringBuffer sb = new StringBuffer(); + + m_ch = getChar(); + while( !isSeparator( m_ch, NULL_SEPARATORS ) ) + { + sb.append( m_ch ); + m_ch = getChar(); + } + + final String argument = sb.toString(); + + //System.out.println( "Arguement:" + argument ); + + m_option.addArgument( argument ); + addOption( m_option ); + m_option = null; + m_state = STATE_NORMAL; + } + } + } + + /** + * Parse Options from Normal mode. + */ + private final void parseNormal() + throws ParseException + { + if( '-' != m_ch ) + { + //Parse the arguments that are not options + final String argument = nextToken( NULL_SEPARATORS ).getValue(); + addOption( new CLOption( argument ) ); + m_state = STATE_NORMAL; + } + else + { + getChar(); // strip the - + + if( 0 == peekAtChar() ) + { + throw new ParseException( "Malformed option -", 0 ); + } + else + { + m_ch = peekAtChar(); + + //if it is a short option then parse it else ... + if( '-' != m_ch ) + { + parseShortOption(); + } + else + { + getChar(); // strip the - + //-- sequence .. it can either mean a change of state + //to STATE_NO_OPTIONS or else a long option + + if( 0 == peekAtChar() ) + { + getChar(); + m_state = STATE_NO_OPTIONS; + } + else + { + //its a long option + final String optionName = nextToken( ARG_SEPARATORS ).getValue(); + final CLOptionDescriptor descriptor = getDescriptorFor( optionName ); + m_isLong = true; + parseOption( descriptor, "--" + optionName ); + } + } + } + } + } + + /** + * Build the m_optionIndex lookup map for the parsed options. + */ + private final void buildOptionIndex() + { + final int size = m_options.size(); + m_optionIndex = new Hashtable( size * 2 ); + + for( int i = 0; i < size; i++ ) + { + final CLOption option = (CLOption)m_options.get( i ); + final CLOptionDescriptor optionDescriptor = + getDescriptorFor( option.getDescriptor().getId() ); + + m_optionIndex.put( new Integer( option.getDescriptor().getId() ), option ); + + if( null != optionDescriptor && + null != optionDescriptor.getName() ) + { + m_optionIndex.put( optionDescriptor.getName(), option ); + } + } + } +} Added: jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLOption.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLOption.java?rev=179898&view=auto ============================================================================== --- jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLOption.java (added) +++ jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLOption.java Fri Jun 3 14:57:28 2005 @@ -0,0 +1,173 @@ +/* + * Copyright 2002-2005 The Apache Software Foundation + * Licensed 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. + */ +package org.apache.commons.cli.avalon; +// Renamed from org.apache.avalon.excalibur.cli + +import java.util.Arrays; + +/** + * Basic class describing an instance of option. + * + * @version $Revision: 1.2 $ $Date: 2005/03/18 15:26:55 $ + */ +public final class CLOption +{ + /** + * Value of [EMAIL PROTECTED] #getId} when the option is a text argument. + */ + public static final int TEXT_ARGUMENT = 0; + + /** + * Default descriptor. Required, since code assumes that getDescriptor will never return null. + */ + private static final CLOptionDescriptor TEXT_ARGUMENT_DESCRIPTOR = + new CLOptionDescriptor( null, CLOptionDescriptor.ARGUMENT_OPTIONAL, TEXT_ARGUMENT, + null ); + + private String[] m_arguments; + private CLOptionDescriptor m_descriptor = TEXT_ARGUMENT_DESCRIPTOR; + + /** + * Retrieve argument to option if it takes arguments. + * + * @return the (first) argument + */ + public final String getArgument() + { + return getArgument( 0 ); + } + + /** + * Retrieve indexed argument to option if it takes arguments. + * + * @param index The argument index, from 0 to + * [EMAIL PROTECTED] #getArgumentCount()}-1. + * @return the argument + */ + public final String getArgument( final int index ) + { + if( null == m_arguments || index < 0 || index >= m_arguments.length ) + { + return null; + } + else + { + return m_arguments[index]; + } + } + + /** + * Retrieve id of option. + * + * The id is eqivalent to character code if it can be a single letter option. + * + * @return the id + * @deprecated use <code>getDescriptor().getId()</code> instead + */ + public final int getId() + { + return m_descriptor == null ? TEXT_ARGUMENT : m_descriptor.getId(); + } + + public final CLOptionDescriptor getDescriptor() + { + return m_descriptor; + } + + /** + * Constructor taking an descriptor + * + * @param descriptor the descriptor iff null, will default to a "text argument" descriptor. + */ + public CLOption( final CLOptionDescriptor descriptor ) + { + if( descriptor != null ) + { + m_descriptor = descriptor; + } + } + + /** + * Constructor taking argument for option. + * + * @param argument the argument + */ + public CLOption( final String argument ) + { + this( (CLOptionDescriptor)null ); + addArgument( argument ); + } + + /** + * Mutator of Argument property. + * + * @param argument the argument + */ + public final void addArgument( final String argument ) + { + if( null == m_arguments ) + { + m_arguments = new String[]{argument}; + } + else + { + final String[] arguments = new String[m_arguments.length + 1]; + System.arraycopy( m_arguments, 0, arguments, 0, m_arguments.length ); + arguments[m_arguments.length] = argument; + m_arguments = arguments; + } + } + + /** + * Get number of arguments. + * + * @return the number of arguments + */ + public final int getArgumentCount() + { + if( null == m_arguments ) + { + return 0; + } + else + { + return m_arguments.length; + } + } + + /** + * Convert to String. + * + * @return the string value + */ + public final String toString() + { + final StringBuffer sb = new StringBuffer(); + sb.append( "[Option " ); + sb.append( (char)m_descriptor.getId() ); + + if( null != m_arguments ) + { + sb.append( ", " ); + sb.append( Arrays.asList( m_arguments ) ); + } + + sb.append( " ]" ); + + return sb.toString(); + } +} Added: jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLOptionDescriptor.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLOptionDescriptor.java?rev=179898&view=auto ============================================================================== --- jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLOptionDescriptor.java (added) +++ jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLOptionDescriptor.java Fri Jun 3 14:57:28 2005 @@ -0,0 +1,226 @@ +/* + * Copyright 2002-2005 The Apache Software Foundation + * Licensed 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. + */ +package org.apache.commons.cli.avalon; +//Renamed from org.apache.avalon.excalibur.cli + +/** + * Basic class describing an type of option. + * Typically, one creates a static array of <code>CLOptionDescriptor</code>s, + * and passes it to [EMAIL PROTECTED] CLArgsParser#CLArgsParser(String[], CLOptionDescriptor[])}. + * + * @version $Revision: 1.2 $ $Date: 2005/03/18 15:26:55 $ + * @see CLArgsParser + * @see CLUtil + */ +public final class CLOptionDescriptor +{ + /** Flag to say that one argument is required */ + public static final int ARGUMENT_REQUIRED = 1 << 1; + /** Flag to say that the argument is optional */ + public static final int ARGUMENT_OPTIONAL = 1 << 2; + /** Flag to say this option does not take arguments */ + public static final int ARGUMENT_DISALLOWED = 1 << 3; + /** Flag to say this option requires 2 arguments */ + public static final int ARGUMENTS_REQUIRED_2 = 1 << 4; + /** Flag to say this option may be repeated on the command line */ + public static final int DUPLICATES_ALLOWED = 1 << 5; + + private final int m_id; + private final int m_flags; + private final String m_name; + private final String m_description; + private final int[] m_incompatible; + + /** + * Constructor. + * + * @param name the name/long option + * @param flags the flags + * @param id the id/character option + * @param description description of option usage + */ + public CLOptionDescriptor( final String name, + final int flags, + final int id, + final String description ) + { + this( name, flags, id, description, + ((flags & CLOptionDescriptor.DUPLICATES_ALLOWED) > 0) + ? new int[0] : new int[]{id} ); + } + + /** + * Constructor. + * + * @param name the name/long option + * @param flags the flags + * @param id the id/character option + * @param description description of option usage + * @param incompatible an array listing the ids of all incompatible options + * @deprecated use the version with the array of CLOptionDescriptor's + */ + public CLOptionDescriptor( final String name, + final int flags, + final int id, + final String description, + final int[] incompatible ) + { + m_id = id; + m_name = name; + m_flags = flags; + m_description = description; + m_incompatible = incompatible; + + int modeCount = 0; + if( (ARGUMENT_REQUIRED & flags) == ARGUMENT_REQUIRED ) + { + modeCount++; + } + if( (ARGUMENT_OPTIONAL & flags) == ARGUMENT_OPTIONAL ) + { + modeCount++; + } + if( (ARGUMENT_DISALLOWED & flags) == ARGUMENT_DISALLOWED ) + { + modeCount++; + } + if( (ARGUMENTS_REQUIRED_2 & flags) == ARGUMENTS_REQUIRED_2 ) + { + modeCount++; + } + + if( 0 == modeCount ) + { + final String message = "No mode specified for option " + this; + throw new IllegalStateException( message ); + } + else if( 1 != modeCount ) + { + final String message = "Multiple modes specified for option " + this; + throw new IllegalStateException( message ); + } + } + + /** + * Constructor. + * + * @param name the name/long option + * @param flags the flags + * @param id the id/character option + * @param description description of option usage + */ + public CLOptionDescriptor( final String name, + final int flags, + final int id, + final String description, + final CLOptionDescriptor[] incompatible ) + { + m_id = id; + m_name = name; + m_flags = flags; + m_description = description; + + m_incompatible = new int[incompatible.length]; + for( int i = 0; i < incompatible.length; i++ ) + { + m_incompatible[i] = incompatible[i].getId(); + } + } + + /** + * @deprecated Use the correctly spelled [EMAIL PROTECTED] #getIncompatible} instead. + * @return the array of incompatible option ids + */ + protected final int[] getIncompatble() + { + return getIncompatible(); + } + + /** + * Get the array of incompatible option ids. + * + * @return the array of incompatible option ids + */ + protected final int[] getIncompatible() + { + return m_incompatible; + } + + /** + * Retrieve textual description. + * + * @return the description + */ + public final String getDescription() + { + return m_description; + } + + /** + * Retrieve flags about option. + * Flags include details such as whether it allows parameters etc. + * + * @return the flags + */ + public final int getFlags() + { + return m_flags; + } + + /** + * Retrieve the id for option. + * The id is also the character if using single character options. + * + * @return the id + */ + public final int getId() + { + return m_id; + } + + /** + * Retrieve name of option which is also text for long option. + * + * @return name/long option + */ + public final String getName() + { + return m_name; + } + + /** + * Convert to String. + * + * @return the converted value to string. + */ + public final String toString() + { + final StringBuffer sb = new StringBuffer(); + sb.append( "[OptionDescriptor " ); + sb.append( m_name ); + sb.append( "[OptionDescriptor " ); + sb.append( m_name ); + sb.append( ", " ); + sb.append( m_id ); + sb.append( ", " ); + sb.append( m_flags ); + sb.append( ", " ); + sb.append( m_description ); + sb.append( " ]" ); + return sb.toString(); + } +} Added: jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLUtil.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLUtil.java?rev=179898&view=auto ============================================================================== --- jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLUtil.java (added) +++ jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/CLUtil.java Fri Jun 3 14:57:28 2005 @@ -0,0 +1,118 @@ +/* + * Copyright 2002-2005 The Apache Software Foundation + * Licensed 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. + */ +package org.apache.commons.cli.avalon; +//Renamed from org.apache.avalon.excalibur.cli + +/** + * CLUtil offers basic utility operations for use both internal and external to package. + * + * @version $Revision: 1.2 $ $Date: 2005/03/18 15:26:55 $ + * @see CLOptionDescriptor + */ +public final class CLUtil +{ + private static final int MAX_DESCRIPTION_COLUMN_LENGTH = 60; + + /** + * Format options into StringBuffer and return. This is typically used to + * print "Usage" text in response to a "--help" or invalid option. + * + * @param options the option descriptors + * @return the formatted description/help for options + */ + public static final StringBuffer describeOptions( final CLOptionDescriptor[] options ) + { + final String lSep = System.getProperty( "line.separator" ); + final StringBuffer sb = new StringBuffer(); + + for( int i = 0; i < options.length; i++ ) + { + final char ch = (char)options[i].getId(); + final String name = options[i].getName(); + String description = options[i].getDescription(); + int flags = options[i].getFlags(); + boolean argumentRequired = + ((flags & CLOptionDescriptor.ARGUMENT_REQUIRED) == + CLOptionDescriptor.ARGUMENT_REQUIRED); + boolean twoArgumentsRequired = + ((flags & CLOptionDescriptor.ARGUMENTS_REQUIRED_2) == + CLOptionDescriptor.ARGUMENTS_REQUIRED_2); + boolean needComma = false; + if( twoArgumentsRequired ) + { + argumentRequired = true; + } + + sb.append( '\t' ); + + if( Character.isLetter( ch ) ) + { + sb.append( "-" ); + sb.append( ch ); + needComma = true; + } + + if( null != name ) + { + if( needComma ) + { + sb.append( ", " ); + } + + sb.append( "--" ); + sb.append( name ); + } + + if( argumentRequired ) + { + sb.append( " <argument>" ); + } + if( twoArgumentsRequired ) + { + sb.append( "=<value>" ); + } + sb.append( lSep ); + + if( null != description ) + { + while( description.length() > MAX_DESCRIPTION_COLUMN_LENGTH ) + { + final String descriptionPart = + description.substring( 0, MAX_DESCRIPTION_COLUMN_LENGTH ); + description = + description.substring( MAX_DESCRIPTION_COLUMN_LENGTH ); + sb.append( "\t\t" ); + sb.append( descriptionPart ); + sb.append( lSep ); + } + + sb.append( "\t\t" ); + sb.append( description ); + sb.append( lSep ); + } + } + return sb; + } + + /** + * Private Constructor so that no instance can ever be created. + * + */ + private CLUtil() + { + } +} Added: jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/ParserControl.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/ParserControl.java?rev=179898&view=auto ============================================================================== --- jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/ParserControl.java (added) +++ jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/ParserControl.java Fri Jun 3 14:57:28 2005 @@ -0,0 +1,36 @@ +/* + * Copyright 2002-2005 The Apache Software Foundation + * Licensed 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. + */ +package org.apache.commons.cli.avalon; +//Renamed from org.apache.avalon.excalibur.cli + +/** + * ParserControl is used to control particular behaviour of the parser. + * + * @version $Revision: 1.2 $ $Date: 2005/03/18 15:26:55 $ + * @see AbstractParserControl + */ +public interface ParserControl +{ + /** + * Called by the parser to determine whether it should stop + * after last option parsed. + * + * @param lastOptionCode the code of last option parsed + * @return return true to halt, false to continue parsing + */ + boolean isFinished( int lastOptionCode ); +} Added: jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/Token.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/Token.java?rev=179898&view=auto ============================================================================== --- jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/Token.java (added) +++ jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/Token.java Fri Jun 3 14:57:28 2005 @@ -0,0 +1,72 @@ +/* + * Copyright 2002-2005 The Apache Software Foundation + * Licensed 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. + */ +package org.apache.commons.cli.avalon; +//Renamed from org.apache.avalon.excalibur.cli + +/** + * Token handles tokenizing the CLI arguments + * + * @version $Revision: 1.2 $ $Date: 2005/03/18 15:26:55 $ + * @since 4.0 + */ +class Token +{ + /** Type for a separator token */ + public static final int TOKEN_SEPARATOR = 0; + /** Type for a text token */ + public static final int TOKEN_STRING = 1; + + private final int m_type; + private final String m_value; + + /** + * New Token object with a type and value + */ + Token( final int type, final String value ) + { + m_type = type; + m_value = value; + } + + /** + * Get the value of the token + */ + final String getValue() + { + return m_value; + } + + /** + * Get the type of the token + */ + final int getType() + { + return m_type; + } + + /** + * Convert to a string + */ + public final String toString() + { + final StringBuffer sb = new StringBuffer(); + sb.append( m_type ); + sb.append( ":" ); + sb.append( m_value ); + return sb.toString(); + } +} Added: jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/package.html URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/package.html?rev=179898&view=auto ============================================================================== --- jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/package.html (added) +++ jakarta/commons/proper/cli/trunk/src/java/org/apache/commons/cli/avalon/package.html Fri Jun 3 14:57:28 2005 @@ -0,0 +1,164 @@ +<html> + <head> + <title>Package Documentation for org.apache.commons.cli.avalon Package</title> + </head> + <body bgcolor="white"> + Utility code for parsing command-line options. + <br><br> +<p style="font-weight:bold"> +These classes were originally in the Avalon project in the package org.apache.avalon.excalibur.cli +</p> + + <h3>Introduction</h3> + <p>The utilities in <code>org.apache.commons.cli.avalon</code> assist + you in parsing command line options during startup time. It allows you + to associate a short option and a long option to the same command, and + then test for it in a switch statement.</p> + <a name="doc.Usage"></a> + <h3>Usage Example</h3> + <pre> +import java.util.List; + +import org.apache.commons.cli.avalon.CLArgsParser; +import org.apache.commons.cli.avalon.CLOption; +import org.apache.commons.cli.avalon.CLOptionDescriptor; +import org.apache.commons.cli.avalon.CLUtil; + +/** +* Demonstrates the excalibur command-line parsing utility. +* +*/ +public class CLDemo { + // Define our short one-letter option identifiers. + protected static final int HELP_OPT = 'h'; + protected static final int VERSION_OPT = 'v'; + protected static final int MSG_OPT = 'm'; + + /** + * Define the understood options. Each CLOptionDescriptor contains: + * - The "long" version of the option. Eg, "help" means that "--help" will + * be recognised. + * - The option flags, governing the option's argument(s). + * - The "short" version of the option. Eg, 'h' means that "-h" will be + * recognised. + * - A description of the option. + */ + protected static final CLOptionDescriptor [] options = new CLOptionDescriptor [] { + new CLOptionDescriptor("help", + CLOptionDescriptor.ARGUMENT_DISALLOWED, + HELP_OPT, + "print this message and exit"), + new CLOptionDescriptor("version", + CLOptionDescriptor.ARGUMENT_DISALLOWED, + VERSION_OPT, + "print the version information and exit"), + new CLOptionDescriptor("msg", + CLOptionDescriptor.ARGUMENT_REQUIRED, + MSG_OPT, + "the message to print"), + }; + + public static void main(String args[]) { + // Parse the arguments + CLArgsParser parser = new CLArgsParser(args, options); + + if( null != parser.getErrorString() ) { + System.err.println( "Error: " + parser.getErrorString() ); + return; + } + + // Get a list of parsed options + List clOptions = parser.getArguments(); + int size = clOptions.size(); + + for (int i = 0; i < size; i++) { + CLOption option = (CLOption) clOptions.get(i); + + switch (option.getId()) { + case CLOption.TEXT_ARGUMENT: + System.out.println("Unknown arg: "+option.getArgument()); + break; + + case HELP_OPT: + printUsage(); + break; + + case VERSION_OPT: + printVersion(); + break; + + + case MSG_OPT: + System.out.println(option.getArgument()); + break; + } + } + } + + private static void printVersion() { + System.out.println("1.0"); + System.exit(0); + } + + private static void printUsage() { + String lSep = System.getProperty("line.separator"); + StringBuffer msg = new StringBuffer(); + msg.append("------------------------------------------------------------------------ ").append(lSep); + msg.append("Excalibur command-line arg parser demo").append(lSep); + msg.append("Usage: java "+CLDemo.class.getName()+" [options]").append(lSep).append(lSep); + msg.append("Options: ").append(lSep); + msg.append(CLUtil.describeOptions(CLDemo.options).toString()); + System.out.println(msg.toString()); + System.exit(0); + } +} +</pre> + + <h3>Parsing Rules</h3> + <p> + The command line is parsed according to the following rules. There are + two forms of options in this package, the Long form and the Short form. + The long form of an option is preceded by the '--' characters while the + short form is preceded by a single '-'. Some example options would be; + "--an-option", "-a", "--day", "-s -f -a". + </p> + <p> + In the tradition of UNIX programs, the short form of an option can occur + immediately after another short form option. So if 'a', 'b' and 'c' are + short forms of options that take no parameters then the following + command lines are equivalent: "-abc", "-a -bc", "-a -b -c", "-ab -c", etc. + </p> + <p> + Options can also accept arguments if specified. You can specify that an + option requires an argument in which the text immediately following the + option will be considered to be an argument to the option. So if 'a' was an + option that required an argument then the following would be equivalent; + "-abc", "-a bc" (namely the option 'a' with argument 'bc'). + </p> + <p> + Options can also specify optional arguments. In this case if there is any + text immediately following the option character then it is considered an + argument. Otherwise, the option has no arguments. For example if 'a' was an + option that required an optional argument then "-abc" is an option 'a' with + argument "bc" while "-a bc" is an option 'a' with no argument, followed by + the text "bc". </p> + <p>It is also possible to place an '=' sign between the option + and it's argument. So if we assume that a is an option that + requires an argument then the following are all equivalent; + "-a=bc", "-a bc" "-abc". + </p> + <p> + In the case of a long option with an optional argument, the '=' sign is required. + For example. --optarg=1, not --optarg 1. + </p> + <p> + In some cases it is also necessary to disable command line parsing so that you + can pass a text argument to the program that starts with a '-' character. To do + this insert the sequence '--' onto the command line with no text immediately + following it. This will disable processing for the rest of the command line. + The '--' characters will not be passed to the user program. For instance the + line "-- -b" would result in the program being passed the + text "-b" (ie. not as an option). + </p> +</body> +</html> --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]