source: trunk/java-utils/src/de/ugoe/cs/util/console/CommandExecuter.java @ 461

Last change on this file since 461 was 320, checked in by sherbold, 13 years ago
  • improved handling of invalid package names (empty string, null) of the de.ugoe.cs.util.console.CommandExecuter?
File size: 4.8 KB
Line 
1package de.ugoe.cs.util.console;
2
3import java.security.InvalidParameterException;
4import java.util.ArrayList;
5import java.util.List;
6
7/**
8 * <p>
9 * Executes commands. The commands have to implement the {@link Command}
10 * interface and be in packages registered using addCommandPackage().
11 * Additionally, default commands are implemented in the
12 * de.ugoe.cs.util.console.defaultcommands package.
13 * </p>
14 * <p>
15 * This class is implemented as a <i>Singleton</i>.
16 * </p>
17 *
18 * @author Steffen Herbold
19 * @version 1.0
20 */
21public class CommandExecuter {
22
23        /**
24         * <p>
25         * Handle of the CommandExecuter instance.
26         * </p>
27         */
28        private final static CommandExecuter theInstance = new CommandExecuter();
29
30        /**
31         * <p>
32         * Prefix of all command classes.
33         * </p>
34         */
35        private static final String cmdPrefix = "CMD";
36
37        /**
38         * <p>
39         * Name of the package for default commands.
40         * </p>
41         */
42        private static final String defaultPackage = "de.ugoe.cs.util.console.defaultcommands";
43
44        /**
45         * <p>
46         * List of packages in which commands may be defined. The exec methods trys
47         * to load command from these packages in the order they have been added.
48         * </p>
49         * <p>
50         * The de.ugoe.cs.util.console.defaultcommands package has always lowest
51         * priority, unless it is specifically added.
52         * </p>
53         */
54        private List<String> commandPackageList;
55
56        /**
57         * <p>
58         * Returns the instance of CommandExecuter. If no instances exists yet, a
59         * new one is created.
60         * </p>
61         *
62         * @return the instance of CommandExecuter
63         */
64        public static synchronized CommandExecuter getInstance() {
65                return theInstance;
66        }
67
68        /**
69         * <p>
70         * Creates a new CommandExecuter. Private to prevent multiple instances
71         * (Singleton).
72         * </p>
73         */
74        private CommandExecuter() {
75                commandPackageList = new ArrayList<String>();
76        }
77
78        /**
79         * <p>
80         * Adds a package that will be used by {@link #exec(String)} to load command
81         * from.
82         * </p>
83         *
84         * @param pkg
85         *            package where commands are located
86         * @throws InvalidParameterException
87         *             thrown if the package name is null or empty string
88         */
89        public void addCommandPackage(String pkg) {
90                if ("".equals(pkg) || pkg == null) {
91                        throw new InvalidParameterException(
92                                        "package name must not be null or empty string");
93                }
94                commandPackageList.add(pkg);
95        }
96
97        /**
98         * <p>
99         * Executes the command defined by string. A command has the following form
100         * (mix of EBNF and natural language):
101         * </p>
102         * <code>
103         * &lt;command&gt; := &lt;commandname&gt;&lt;whitespace&gt;{&lt;parameter&gt;}<br>
104         * &lt;commandname&gt; := String without whitespaces. Has to be a valid Java class name<br>
105         * &lt;parameter&gt; := &lt;string&gt;|&lt;stringarray&gt;<br>
106         * &lt;string&gt; := &lt;stringwithoutwhitespaces&gt;|&lt;stringwithwhitespaces&gt;
107         * &lt;stringwithoutwhitespaces&gt; := a string without whitespaces<br>
108         * &lt;stringwithoutwhitespaces&gt; := a string, that can have whitespaces, but must be in double quotes<br>
109         * &lt;stringarray&gt; := "["&lt;string&gt;{&lt;whitespace&gt;&lt;string&gt;"]"
110         * </code>
111         *
112         * @param command
113         *            the command as a string
114         */
115        public void exec(String command) {
116                Console.commandNotification(command);
117                Command cmd = null;
118                CommandParser parser = new CommandParser();
119                parser.parse(command);
120                for (int i = 0; cmd == null && i < commandPackageList.size(); i++) {
121                        cmd = loadCMD(commandPackageList.get(i) + "." + cmdPrefix
122                                        + parser.getCommandName());
123                }
124                if (cmd == null) { // check if command is available as default command
125                        cmd = loadCMD(defaultPackage + "." + cmdPrefix
126                                        + parser.getCommandName());
127                }
128                if (cmd == null) {
129                        Console.println("Unknown command");
130                } else {
131                        try {
132                                cmd.run(parser.getParameters());
133                        } catch (InvalidParameterException e) {
134                                cmd.help();
135                        }
136                }
137        }
138
139        /**
140         * <p>
141         * Helper method that loads a class and tries to cast it to {@link Command}.
142         * </p>
143         *
144         * @param className
145         *            qualified name of the class (including package name)
146         * @return if class is available and implement {@link Command} and instance
147         *         of the class, null otherwise
148         */
149        private Command loadCMD(String className) {
150                Command cmd = null;
151                try {
152                        Class<?> cmdClass = Class.forName(className);
153                        cmd = (Command) cmdClass.newInstance();
154                } catch (NoClassDefFoundError e) {
155                        String[] splitResult = e.getMessage().split("CMD");
156                        String correctName = splitResult[splitResult.length - 1].replace(
157                                        ")", "");
158                        Console.println("Did you mean " + correctName + "?");
159                } catch (ClassNotFoundException e) {
160                } catch (IllegalAccessException e) {
161                } catch (InstantiationException e) {
162                } catch (ClassCastException e) {
163                        Console.traceln(className + "found, but does not implement Command");
164                }
165                return cmd;
166        }
167}
Note: See TracBrowser for help on using the repository browser.