📄 clargsparser.java
字号:
/* * Copyright 2001-2004 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. */// This file is pulled from package org.apache.avalon.excalibur.cli Excalibur// version 4.1 (Jan 30, 2002). Only the package name has been changed.package org.apache.axis.utils;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. * * @author <a href="mailto:peter@apache.org">Peter Donald</a> * @since 4.0 */public final class CLArgsParser{ 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; private static final int TOKEN_SEPARATOR = 0; private static final int TOKEN_STRING = 1; private static final char[] ARG2_SEPARATORS = new char[] { (char)0, '=', '-' }; 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 ch; private String[] args; private boolean isLong; private int argIndex; private int stringIndex; private int stringLength; //cached character == Integer.MAX_VALUE when invalid private static final int INVALID = Integer.MAX_VALUE; private int m_lastChar = INVALID; private int m_lastOptionId; private CLOption m_option; private int m_state = STATE_NORMAL; 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 {@link CLOption} with specified id, or * <code>null</code> if no command line option is found. * * @param id the command line option id * @return the {@link 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 {@link CLOption} with specified name, or * <code>null</code> if no command line option is found. * * @param name the command line option name * @return the {@link 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 ) { 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 */ public CLArgsParser( final String[] args, final CLOptionDescriptor[] optionDescriptors, final ParserControl control ) { m_optionDescriptors = optionDescriptors; m_control = control; m_options = new Vector(); this.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.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.getId();// final CLOptionDescriptor descriptor = getDescriptorFor( id ); for( int j = 0; j < incompatible.length; j++ ) { if( id == incompatible[ j ] ) { final CLOption originalOption = (CLOption)arguments.elementAt( original ); final int originalId = originalOption.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 * * @param args[] arguments */ private final void parse() throws ParseException { if( 0 == args.length ) { return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -