📄 cmdhandler.java
字号:
/* * Copyright (c) 2005, John Mettraux, OpenWFE.org * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * . Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * . 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. * * . Neither the name of the "OpenWFE" nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS 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 COPYRIGHT OWNER OR 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. * * $Id: CmdHandler.java,v 1.2 2005/03/21 15:38:26 jmettraux Exp $ */package openwfe.org.shell;import java.io.BufferedReader;import java.io.IOException;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.util.ArrayList;import java.util.Arrays;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * This command line handler can parse a String into a command verb and its arguments, * then execute a method determined by the command verb. * * <p>Legal command verbs are determined by providing an Object that implements methods of the form * * <pre> * public Boolean do_VERB(String[] args) * </pre> * * The CmdHandler constructor will inspect the Object passed to it, find all methods that * implement command verbs, and use the names of those methods (without the leading "do_") * as the list of legal command verbs. * * <p>The list of verbs is sorted alphabetically. When parsing a command line, abbreviations are * allowed, with the first verb matching the abbreviation being used. Therefore, entering * "a" with legal verbs "aa" and "ab" will cause the method do_aa() to be invoked. * * <p>Supoport for help methods is also provided. For a given verb VERB, the command "help VERB" * will result in the method "public void help_VERB()" being invoked. The command "help" by itself * will list the legal verbs. * * <p>To make the whole thing even easier, this class also provides a command loop which handles * user input, parsing, and invoking of work methods. This means that all the input stuff can * be handled by this class, and the classes that do the real work need only provide the * do_VERB() (and optionally the help_VERB()) methods. * * @author Peter Mayne * */public class CmdHandler{ // Invoked methods must return one of these. // public final static Boolean DO_NOT_EXIT = new Boolean(false); public final static Boolean DO_EXIT = new Boolean(true); // Find all words (containing any character except space and double quote) // and all character sequences surrounded by double quotes. // private final Pattern p = Pattern.compile("[^ \"]+|\".*\""); private String[] verbs; // The object supplying the do_VERB(String[]) and optional help_VERB() methods. // private final Object commandObject; // The results of parsing a command line. // private String verb = null; private String[] args = null; /** * Create a new CmdHandler that recognises the command verbs in the supplied Object. * * @param commands */ public CmdHandler(Object o) { commandObject = o; // Find all methods implementing a verb. // ArrayList methodList = new ArrayList(); Method[] methods = commandObject.getClass().getDeclaredMethods(); for(int i=0; i<methods.length; i++) { // Must return Boolean // if(methods[i].getReturnType().equals(Boolean.class)) { // Must be public and non-static. // int modifier = methods[i].getModifiers(); if((modifier&Modifier.PUBLIC)!=0 && (modifier&Modifier.STATIC)==0) { // Must have a single parameter of type String[]. // Class[] paramTypes = methods[i].getParameterTypes(); if(paramTypes.length==1 && paramTypes[0].equals(String[].class)) { // Must start with "do_". // if(methods[i].getName().startsWith("do_")) { methodList.add(methods[i].getName().substring(3)); } } } } } // If the commandObject does not implement any verbs, it's not worth going on. // if(methodList.size()==0) { throw new IllegalArgumentException("No public do_VERB(String[]) methods were found."); } // Add a "help" verb. If nothing else, we can list the legal verbs. // methodList.add("help"); // We now have our list of verbs. verbs = new String[methodList.size()]; verbs = (String[])methodList.toArray(verbs); Arrays.sort(verbs); } /** * Parse a line into its parts: an initial verb, followed by optional arguments. * The command and arguments are separated by whitespace. Double quotes may be used to * specify arguments containing whitespace. * * <p>Command verbs may be abbreviated: if the list of verbs is <code>{"exit","quit"}</code>, * the input verb "e" will be recognised as "exit". The verb list is scanned from the beginning, * so a verb list of <code>{"save","set"}</code> with input verb "s" will be unambiguously recognised * as "save". * * @param line */ public void parse(String line) { verb = null; args = null; Matcher m = p.matcher(line.trim()); if(m.find()) { // Fetch the command verb. // String v = m.group().toLowerCase(); // Do we have a recognised verb? // for(int i=0; i<verbs.length; i++) { if(verbs[i].startsWith(v)) { verb = verbs[i]; break; } } // If we found a legal verb... // if(verb!=null) { // ...fetch the remaining arguments. // ArrayList argsList = new ArrayList(); while(m.find()) { String arg = m.group(); if(arg.startsWith("\"") && arg.endsWith("\"")) { arg = arg.substring(1, arg.length()-1); } argsList.add(arg); } args = new String[argsList.size()]; args = (String[])argsList.toArray(args); } } else { args = new String[0]; } } /** * The command verb in lower case. * * @return The lower case command verb as a String. This is null if * there was no command verb. */ public String getVerb() { return verb; } /** * The command arguments. * * @return The arguments as a String[], in their original case. * Arguments containing whitespace have their surrounding double quotes stripped away. * When a legal command is found, this is always a String[], even if it has zero elements. * If the verb is null, then args is also null. */ public String[] getArgs() { return args; } /** * Given a successfully parsed command line, call a corresponding method in the specified * Object. * * <p>For a verb "VERB", the method "public Boolean do_VERB(String[] args)" will be called, * where "args" is the getArgs() from the parsed command line. The called method must return * a Boolean indicating whether the command input should be terminated (such as a "quit" command). * * <p>The verb "help" is treated specially. If "help" is specified by itself, the available verbs * will be displayed. If an argument is given, the corresponding verb will be looked up and the * method "public void help_VERB()" will be called. * * @param o The Object whose do_VERB() or help_VERB() method will be called. * * @return A boolean indicating whether the command input loop should be terminated. */ public boolean invoke(Object o) { boolean exiting = false; if(getVerb().equals("help")) { help(o, getArgs()); return false; } String methodName = "do_" + getVerb(); try { Method command = o.getClass().getDeclaredMethod(methodName, new Class[] { String[].class }); Boolean b = (Boolean)command.invoke(o, new Object[] { getArgs() }); exiting = b.booleanValue(); } catch(InvocationTargetException ite) { System.out.println("\n" + ite.getCause().toString() + "\n"); } catch (NoSuchMethodException nsme) { System.out.println("Unimplemented command."); } catch (Throwable t) { t.printStackTrace(); } return exiting; } private void help(Object o, String[] args) { if (args.length < 1) { System.out.println(); System.out.println("help [<command name>]"); System.out.println("\nAvailable commands are:"); for (int i = 0; i < verbs.length; i++) { System.out.print(verbs[i] + " "); } System.out.println(); } else { String cmd = args[0].toLowerCase(); boolean found = false; for(int i=0; i<verbs.length; i++) { if(verbs[i].startsWith(cmd)) { try { String methodName = "help_" + verbs[i]; java.lang.reflect.Method command = o.getClass().getDeclaredMethod(methodName, new Class[] { }); command.invoke(o, new Object[] { }); } catch(Throwable t) { System.out.println("No help is available for command " + verbs[i] + "."); } found = true; break; } } if(!found) { System.out.println("Unrecognised command."); } } } /** * An input command loop that will do the parsing and invoking using the other * methods in this class. * * <p>A typical reader would be supplied by <code>new BufferedReader(new InputStreamReader(System.in))</code>. * * @param prompt The input prompt. * @param reader Where are we reading input from? */ public void commandLoop(String prompt, BufferedReader reader) { boolean exiting = false; while (!exiting) { String line; try { do { System.out.print(prompt); line = reader.readLine().trim(); } while(line.length()==0); } catch (IOException ioe) { break; } parse(line); if(getVerb()!=null) { if(invoke(commandObject)) { break; } } else { System.out.println("Unrecognised command."); } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -