diff options
Diffstat (limited to 'OpenSim/Region/Environment/Modules/ModuleFramework')
-rw-r--r-- | OpenSim/Region/Environment/Modules/ModuleFramework/Commander.cs | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/OpenSim/Region/Environment/Modules/ModuleFramework/Commander.cs b/OpenSim/Region/Environment/Modules/ModuleFramework/Commander.cs new file mode 100644 index 0000000..a17348e --- /dev/null +++ b/OpenSim/Region/Environment/Modules/ModuleFramework/Commander.cs | |||
@@ -0,0 +1,271 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | |||
5 | using OpenSim.Region.Environment.Interfaces; | ||
6 | |||
7 | namespace OpenSim.Region.Environment.Modules.ModuleFramework | ||
8 | { | ||
9 | /// <summary> | ||
10 | /// A single function call encapsulated in a class which enforces arguments when passing around as Object[]'s. | ||
11 | /// Used for console commands and script API generation | ||
12 | /// </summary> | ||
13 | public class Command : ICommand | ||
14 | { | ||
15 | private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
16 | |||
17 | private Action<Object[]> m_command; | ||
18 | private string m_name; | ||
19 | private string m_help; | ||
20 | private List<CommandArgument> m_args = new List<CommandArgument>(); | ||
21 | |||
22 | public Command(string name, Action<Object[]> command, string help) | ||
23 | { | ||
24 | m_name = name; | ||
25 | m_command = command; | ||
26 | m_help = help; | ||
27 | } | ||
28 | |||
29 | public void AddArgument(string name, string helptext, string type) | ||
30 | { | ||
31 | m_args.Add(new CommandArgument(name, helptext, type)); | ||
32 | } | ||
33 | |||
34 | public string Name | ||
35 | { | ||
36 | get { return m_name; } | ||
37 | } | ||
38 | |||
39 | public string Help | ||
40 | { | ||
41 | get { return m_help; } | ||
42 | } | ||
43 | |||
44 | public Dictionary<string, string> Arguments | ||
45 | { | ||
46 | get | ||
47 | { | ||
48 | Dictionary<string, string> tmp = new Dictionary<string, string>(); | ||
49 | foreach (CommandArgument arg in m_args) | ||
50 | { | ||
51 | tmp.Add(arg.Name, arg.ArgumentType); | ||
52 | } | ||
53 | return tmp; | ||
54 | } | ||
55 | } | ||
56 | |||
57 | public void ShowConsoleHelp() | ||
58 | { | ||
59 | m_log.Info("== " + Name + " =="); | ||
60 | m_log.Info(m_help); | ||
61 | m_log.Info("= Parameters ="); | ||
62 | foreach (CommandArgument arg in m_args) | ||
63 | { | ||
64 | m_log.Info("* " + arg.Name + " (" + arg.ArgumentType + ")"); | ||
65 | m_log.Info("\t" + arg.HelpText); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | public void Run(Object[] args) | ||
70 | { | ||
71 | Object[] cleanArgs = new Object[m_args.Count]; | ||
72 | |||
73 | if (args.Length < cleanArgs.Length) | ||
74 | { | ||
75 | m_log.Error("Missing " + (cleanArgs.Length - args.Length) + " argument(s)"); | ||
76 | ShowConsoleHelp(); | ||
77 | return; | ||
78 | } | ||
79 | if (args.Length > cleanArgs.Length) | ||
80 | { | ||
81 | m_log.Error("Too many arguments for this command. Type '<module> <command> help' for help."); | ||
82 | return; | ||
83 | } | ||
84 | |||
85 | int i = 0; | ||
86 | foreach (Object arg in args) | ||
87 | { | ||
88 | if (string.IsNullOrEmpty(arg.ToString())) | ||
89 | { | ||
90 | m_log.Error("Empty arguments are not allowed"); | ||
91 | return; | ||
92 | } | ||
93 | try | ||
94 | { | ||
95 | switch (m_args[i].ArgumentType) | ||
96 | { | ||
97 | case "String": | ||
98 | m_args[i].ArgumentValue = arg.ToString(); | ||
99 | break; | ||
100 | case "Integer": | ||
101 | m_args[i].ArgumentValue = Int32.Parse(arg.ToString()); | ||
102 | break; | ||
103 | case "Double": | ||
104 | m_args[i].ArgumentValue = Double.Parse(arg.ToString()); | ||
105 | break; | ||
106 | case "Boolean": | ||
107 | m_args[i].ArgumentValue = Boolean.Parse(arg.ToString()); | ||
108 | break; | ||
109 | default: | ||
110 | m_log.Error("Unknown desired type for argument " + m_args[i].Name + " on command " + m_name); | ||
111 | break; | ||
112 | } | ||
113 | } | ||
114 | catch (FormatException) | ||
115 | { | ||
116 | m_log.Error("Argument number " + (i + 1) + | ||
117 | " (" + m_args[i].Name + ") must be a valid " + | ||
118 | m_args[i].ArgumentType.ToLower() + "."); | ||
119 | } | ||
120 | cleanArgs[i] = m_args[i].ArgumentValue; | ||
121 | |||
122 | i++; | ||
123 | } | ||
124 | |||
125 | m_command.Invoke(cleanArgs); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | /// <summary> | ||
130 | /// A single command argument, contains name, type and at runtime, value. | ||
131 | /// </summary> | ||
132 | public class CommandArgument | ||
133 | { | ||
134 | private string m_name; | ||
135 | private string m_help; | ||
136 | private string m_type; | ||
137 | private Object m_val; | ||
138 | |||
139 | public CommandArgument(string name, string help, string type) | ||
140 | { | ||
141 | m_name = name; | ||
142 | m_help = help; | ||
143 | m_type = type; | ||
144 | } | ||
145 | |||
146 | public string Name | ||
147 | { | ||
148 | get { return m_name; } | ||
149 | } | ||
150 | |||
151 | public string HelpText | ||
152 | { | ||
153 | get { return m_help; } | ||
154 | } | ||
155 | |||
156 | public string ArgumentType | ||
157 | { | ||
158 | get { return m_type; } | ||
159 | } | ||
160 | |||
161 | public Object ArgumentValue | ||
162 | { | ||
163 | get { return m_val; } | ||
164 | set { m_val = value; } | ||
165 | } | ||
166 | } | ||
167 | |||
168 | /// <summary> | ||
169 | /// A class to enable modules to register console and script commands, which enforces typing and valid input. | ||
170 | /// </summary> | ||
171 | public class Commander : ICommander | ||
172 | { | ||
173 | private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
174 | private Dictionary<string, ICommand> m_commands = new Dictionary<string, ICommand>(); | ||
175 | private string m_name; | ||
176 | |||
177 | public Commander(string name) | ||
178 | { | ||
179 | m_name = name; | ||
180 | } | ||
181 | |||
182 | public void RegisterCommand(string commandName, ICommand command) | ||
183 | { | ||
184 | m_commands[commandName] = command; | ||
185 | } | ||
186 | |||
187 | void ShowConsoleHelp() | ||
188 | { | ||
189 | m_log.Info("===" + m_name + "==="); | ||
190 | foreach (ICommand com in m_commands.Values) | ||
191 | { | ||
192 | m_log.Info("* " + com.Name + " - " + com.Help); | ||
193 | } | ||
194 | } | ||
195 | |||
196 | string EscapeRuntimeAPICommand(string command) | ||
197 | { | ||
198 | command = command.Replace('-', '_'); | ||
199 | StringBuilder tmp = new StringBuilder(command); | ||
200 | tmp[0] = tmp[0].ToString().ToUpper().ToCharArray()[0]; | ||
201 | |||
202 | return tmp.ToString(); | ||
203 | } | ||
204 | |||
205 | /// <summary> | ||
206 | /// Generates a runtime C# class which can be compiled and inserted via reflection to enable modules to register new script commands | ||
207 | /// </summary> | ||
208 | /// <returns>Returns C# source code to create a binding</returns> | ||
209 | public string GenerateRuntimeAPI() | ||
210 | { | ||
211 | string classSrc = "\n\tpublic class " + m_name + " {\n"; | ||
212 | foreach (ICommand com in m_commands.Values) | ||
213 | { | ||
214 | classSrc += "\tpublic void " + EscapeRuntimeAPICommand(com.Name) + "( "; | ||
215 | foreach (KeyValuePair<string, string> arg in com.Arguments) | ||
216 | { | ||
217 | classSrc += arg.Value + " " + Framework.Util.Md5Hash(arg.Key) + ","; | ||
218 | } | ||
219 | classSrc = classSrc.Remove(classSrc.Length - 1); // Delete the last comma | ||
220 | classSrc += " )\n\t{\n"; | ||
221 | classSrc += "\t\tObject[] args = new Object[" + com.Arguments.Count.ToString() + "];\n"; | ||
222 | int i = 0; | ||
223 | foreach (KeyValuePair<string, string> arg in com.Arguments) | ||
224 | { | ||
225 | classSrc += "\t\targs[" + i.ToString() + "] = " + Framework.Util.Md5Hash(arg.Key) + " " + ";\n"; | ||
226 | i++; | ||
227 | } | ||
228 | classSrc += "\t\tGetCommander(\"" + m_name + "\").Run(\"" + com.Name + "\", args);\n"; | ||
229 | classSrc += "\t}\n"; | ||
230 | } | ||
231 | classSrc += "}\n"; | ||
232 | |||
233 | return classSrc; | ||
234 | } | ||
235 | |||
236 | /// <summary> | ||
237 | /// Runs a specified function with attached arguments | ||
238 | /// *** <b>DO NOT CALL DIRECTLY.</b> *** | ||
239 | /// Call ProcessConsoleCommand instead if handling human input. | ||
240 | /// </summary> | ||
241 | /// <param name="function">The function name to call</param> | ||
242 | /// <param name="args">The function parameters</param> | ||
243 | public void Run(string function, object[] args) | ||
244 | { | ||
245 | m_commands[function].Run(args); | ||
246 | } | ||
247 | |||
248 | public void ProcessConsoleCommand(string function, string[] args) | ||
249 | { | ||
250 | if (m_commands.ContainsKey(function)) | ||
251 | { | ||
252 | if (args[0] == "help") | ||
253 | { | ||
254 | m_commands[function].ShowConsoleHelp(); | ||
255 | } | ||
256 | else | ||
257 | { | ||
258 | m_commands[function].Run(args); | ||
259 | } | ||
260 | } | ||
261 | else | ||
262 | { | ||
263 | if (function != "help") | ||
264 | m_log.Error("Invalid command - No such command exists"); | ||
265 | if (function == "api") | ||
266 | m_log.Info(GenerateRuntimeAPI()); | ||
267 | ShowConsoleHelp(); | ||
268 | } | ||
269 | } | ||
270 | } | ||
271 | } | ||