package de.ugoe.cs.util.console; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.List; /** *

* Executes commands. The commands have to implement the {@link Command} * interface and be in packages registered using addCommandPackage(). * Additionally, default commands are implemented in the * de.ugoe.cs.util.console.defaultcommands package. *

*

* This class is implemented as a Singleton. *

* * @author Steffen Herbold * @version 1.0 */ public class CommandExecuter { /** *

* Handle of the CommandExecuter instance. *

*/ private final static CommandExecuter theInstance = new CommandExecuter(); /** *

* Prefix of all command classes. *

*/ private static final String cmdPrefix = "CMD"; /** *

* Name of the package for default commands. *

*/ private static final String defaultPackage = "de.ugoe.cs.util.console.defaultcommands"; /** *

* List of packages in which commands may be defined. The exec methods trys * to load command from these packages in the order they have been added. *

*

* The de.ugoe.cs.util.console.defaultcommands package has always lowest * priority, unless it is specifically added. *

*/ private List commandPackageList; /** *

* Returns the instance of CommandExecuter. If no instances exists yet, a * new one is created. *

* * @return the instance of CommandExecuter */ public static synchronized CommandExecuter getInstance() { return theInstance; } /** *

* Creates a new CommandExecuter. Private to prevent multiple instances * (Singleton). *

*/ private CommandExecuter() { commandPackageList = new ArrayList(); } /** *

* Adds a package that will be used by {@link #exec(String)} to load command * from. *

* * @param pkg * package where commands are located * @throws InvalidParameterException * thrown if the package name is null or empty string */ public void addCommandPackage(String pkg) { if ("".equals(pkg) || pkg == null) { throw new InvalidParameterException( "package name must not be null or empty string"); } commandPackageList.add(pkg); } /** *

* Executes the command defined by string. A command has the following form * (mix of EBNF and natural language): *

* * <command> := <commandname><whitespace>{<parameter>}
* <commandname> := String without whitespaces. Has to be a valid Java class name
* <parameter> := <string>|<stringarray>
* <string> := <stringwithoutwhitespaces>|<stringwithwhitespaces> * <stringwithoutwhitespaces> := a string without whitespaces
* <stringwithoutwhitespaces> := a string, that can have whitespaces, but must be in double quotes
* <stringarray> := "["<string>{<whitespace><string>"]" *
* * @param command * the command as a string */ public void exec(String command) { Console.commandNotification(command); Command cmd = null; CommandParser parser = new CommandParser(); parser.parse(command); for (int i = 0; cmd == null && i < commandPackageList.size(); i++) { cmd = loadCMD(commandPackageList.get(i) + "." + cmdPrefix + parser.getCommandName()); } if (cmd == null) { // check if command is available as default command cmd = loadCMD(defaultPackage + "." + cmdPrefix + parser.getCommandName()); } if (cmd == null) { Console.println("Unknown command"); } else { try { cmd.run(parser.getParameters()); } catch (InvalidParameterException e) { cmd.help(); } } } /** *

* Helper method that loads a class and tries to cast it to {@link Command}. *

* * @param className * qualified name of the class (including package name) * @return if class is available and implement {@link Command} and instance * of the class, null otherwise */ private Command loadCMD(String className) { Command cmd = null; try { Class cmdClass = Class.forName(className); cmd = (Command) cmdClass.newInstance(); } catch (NoClassDefFoundError e) { String[] splitResult = e.getMessage().split("CMD"); String correctName = splitResult[splitResult.length - 1].replace( ")", ""); Console.println("Did you mean " + correctName + "?"); } catch (ClassNotFoundException e) { } catch (IllegalAccessException e) { } catch (InstantiationException e) { } catch (ClassCastException e) { Console.traceln(className + "found, but does not implement Command"); } return cmd; } }