From 54c6a920baa0ef02a9ea09e08cc1effcef3b0a3a Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 7 Feb 2009 12:25:39 +0000 Subject: Replace the console for all OpenSim apps with a new console featuring command line editing, context sensitive help (press ? at any time), command line history, a new plugin command system and new appender features thet let you type while the console is scrolling. Seamlessly integrates the ICommander interfaces. --- OpenSim/Framework/Console/ConsoleBase.cs | 661 ++++++++++--- OpenSim/Framework/Console/ConsoleCallbacksBase.cs | 35 - OpenSim/Framework/Console/OpenSimAppender.cs | 16 + OpenSim/Framework/IScene.cs | 3 + OpenSim/Framework/Servers/BaseOpenSimServer.cs | 119 +-- OpenSim/Grid/AssetServer/Main.cs | 6 +- OpenSim/Grid/GridServer/GridServerBase.cs | 63 +- OpenSim/Grid/InventoryServer/Main.cs | 21 +- OpenSim/Grid/MessagingServer/Main.cs | 42 +- OpenSim/Grid/UserServer/Main.cs | 94 +- OpenSim/Region/Application/Application.cs | 15 +- OpenSim/Region/Application/HGOpenSimNode.cs | 27 +- OpenSim/Region/Application/OpenSim.cs | 1033 ++++++++++---------- OpenSim/Region/Application/OpenSimBase.cs | 40 + .../Region/ClientStack/RegionApplicationBase.cs | 2 + .../Framework/InterfaceCommander/Command.cs | 12 + .../Modules/World/Permissions/PermissionsModule.cs | 148 +-- OpenSim/Region/Framework/Interfaces/ICommand.cs | 1 + OpenSim/Region/Framework/Scenes/Scene.cs | 18 +- OpenSim/Region/Framework/Scenes/SceneBase.cs | 8 + .../Shared/Api/Implementation/LSL_Api.cs | 6 - OpenSim/TestSuite/BotManager.cs | 51 +- OpenSim/Tools/pCampBot/BotManager.cs | 85 +- 23 files changed, 1471 insertions(+), 1035 deletions(-) delete mode 100644 OpenSim/Framework/Console/ConsoleCallbacksBase.cs diff --git a/OpenSim/Framework/Console/ConsoleBase.cs b/OpenSim/Framework/Console/ConsoleBase.cs index 30af23a..f990748 100644 --- a/OpenSim/Framework/Console/ConsoleBase.cs +++ b/OpenSim/Framework/Console/ConsoleBase.cs @@ -26,22 +26,250 @@ */ using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Net; +using System.Text; using System.Reflection; -using System.Text.RegularExpressions; +using System.Diagnostics; +using System.Collections.Generic; using log4net; namespace OpenSim.Framework.Console { + public delegate void CommandDelegate(string module, string[] cmd); + + public class Commands + { + private class CommandInfo + { + public string module; + public string help_text; + public string long_help; + public CommandDelegate fn; + } + + private Dictionary tree = + new Dictionary(); + + public List GetHelp() + { + List help = new List(); + + help.AddRange(CollectHelp(tree)); + + help.Sort(); + + return help; + } + + private List CollectHelp(Dictionary dict) + { + List result = new List(); + + foreach (KeyValuePair kvp in dict) + { + if (kvp.Value is Dictionary) + { + result.AddRange(CollectHelp((Dictionary)kvp.Value)); + } + else + { + if (((CommandInfo)kvp.Value).long_help != String.Empty) + result.Add(((CommandInfo)kvp.Value).help_text+" - "+ + ((CommandInfo)kvp.Value).long_help); + } + } + return result; + } + + public void AddCommand(string module, string command, string help, string longhelp, CommandDelegate fn) + { + string[] parts = Parser.Parse(command); + + Dictionary current = tree; + foreach (string s in parts) + { + if (current.ContainsKey(s)) + { + if (current[s] is Dictionary) + { + current = (Dictionary)current[s]; + } + else + return; + } + else + { + current[s] = new Dictionary(); + current = (Dictionary)current[s]; + } + } + + if (current.ContainsKey(String.Empty)) + return; + CommandInfo info = new CommandInfo(); + info.module = module; + info.help_text = help; + info.long_help = longhelp; + info.fn = fn; + current[String.Empty] = info; + } + + public string[] FindNextOption(string[] cmd, bool term) + { + Dictionary current = tree; + + int remaining = cmd.Length; + + foreach (string s in cmd) + { + remaining--; + + List found = new List(); + + foreach (string opt in current.Keys) + { + if (opt.StartsWith(s)) + { + found.Add(opt); + } + } + + if (found.Count == 1 && (remaining != 0 || term)) + { + current = (Dictionary)current[found[0]]; + } + else if (found.Count > 0) + { + return found.ToArray(); + } + else + { + break; +// return new string[] {""}; + } + } + + if (current.Count > 1) + { + List choices = new List(); + + bool addcr = false; + foreach (string s in current.Keys) + { + if (s == String.Empty) + { + CommandInfo ci = (CommandInfo)current[String.Empty]; + if (ci.fn != null) + addcr = true; + } + else + choices.Add(s); + } + if (addcr) + choices.Add(""); + return choices.ToArray(); + } + + if (current.ContainsKey(String.Empty)) + return new string[] { "Command help: "+((CommandInfo)current[String.Empty]).help_text}; + + return new string[] { new List(current.Keys)[0] }; + } + + public string[] Resolve(string[] cmd) + { + string[] result = cmd; + int index = -1; + + Dictionary current = tree; + + foreach (string s in cmd) + { + index++; + + List found = new List(); + + foreach (string opt in current.Keys) + { + if (opt.StartsWith(s)) + { + found.Add(opt); + } + } + + if (found.Count == 1) + { + result[index] = found[0]; + current = (Dictionary)current[found[0]]; + } + else if (found.Count > 0) + { + return new string[0]; + } + else + { + break; + } + } + + if (current.ContainsKey(String.Empty)) + { + CommandInfo ci = (CommandInfo)current[String.Empty]; + if (ci.fn == null) + return new string[0]; + ci.fn(ci.module, result); + return result; + } + return new string[0]; + } + } + + public class Parser + { + public static string[] Parse(string text) + { + List result = new List(); + + int index; + + string[] unquoted = text.Split(new char[] {'"'}); + + for (index = 0 ; index < unquoted.Length ; index++) + { + if (index % 2 == 0) + { + string[] words = unquoted[index].Split(new char[] {' '}); + foreach (string w in words) + { + if (w != String.Empty) + result.Add(w); + } + } + else + { + result.Add(unquoted[index]); + } + } + + return result.ToArray(); + } + } + public class ConsoleBase { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private readonly object m_syncRoot = new object(); - public conscmd_callback m_cmdParser; + private int y = -1; + private int cp = 0; + private int h = 1; + private string prompt = "# "; + private StringBuilder cmdline = new StringBuilder(); + public Commands Commands = new Commands(); + private bool echo = true; + private List history = new List(); + + public object ConsoleScene = null; /// /// The default prompt text. @@ -53,15 +281,19 @@ namespace OpenSim.Framework.Console } protected string m_defaultPrompt; - /// - /// Constructor. - /// - /// - /// - public ConsoleBase(string defaultPrompt, conscmd_callback cmdparser) + public ConsoleBase(string defaultPrompt) { DefaultPrompt = defaultPrompt; - m_cmdParser = cmdparser; + + Commands.AddCommand("console", "help", "help", "Get command list", Help); + } + + private void AddToHistory(string text) + { + while (history.Count >= 100) + history.RemoveAt(0); + + history.Add(text); } /// @@ -95,8 +327,7 @@ namespace OpenSim.Framework.Console /// WriteLine-style message arguments public void Warn(string sender, string format, params object[] args) { - WritePrefixLine(DeriveColor(sender), sender); - WriteNewLine(ConsoleColor.Yellow, format, args); + WriteNewLine(DeriveColor(sender), sender, ConsoleColor.Yellow, format, args); } /// @@ -117,10 +348,8 @@ namespace OpenSim.Framework.Console /// WriteLine-style message arguments public void Notice(string sender, string format, params object[] args) { - WritePrefixLine(DeriveColor(sender), sender); - WriteNewLine(ConsoleColor.White, format, args); + WriteNewLine(DeriveColor(sender), sender, ConsoleColor.White, format, args); } - /// /// Sends an error to the current console output /// @@ -139,8 +368,7 @@ namespace OpenSim.Framework.Console /// WriteLine-style message arguments public void Error(string sender, string format, params object[] args) { - WritePrefixLine(DeriveColor(sender), sender); - Error(format, args); + WriteNewLine(DeriveColor(sender), sender, ConsoleColor.Red, format, args); } /// @@ -161,8 +389,7 @@ namespace OpenSim.Framework.Console /// WriteLine-style message arguments public void Status(string sender, string format, params object[] args) { - WritePrefixLine(DeriveColor(sender), sender); - WriteNewLine(ConsoleColor.Blue, format, args); + WriteNewLine(DeriveColor(sender), sender, ConsoleColor.Blue, format, args); } [Conditional("DEBUG")] @@ -174,12 +401,60 @@ namespace OpenSim.Framework.Console [Conditional("DEBUG")] public void Debug(string sender, string format, params object[] args) { - WritePrefixLine(DeriveColor(sender), sender); - WriteNewLine(ConsoleColor.Gray, format, args); + WriteNewLine(DeriveColor(sender), sender, ConsoleColor.Gray, format, args); + } + + private void WriteNewLine(ConsoleColor senderColor, string sender, ConsoleColor color, string format, params object[] args) + { + lock (cmdline) + { + if (y != -1) + { + System.Console.CursorTop = y; + System.Console.CursorLeft = 0; + + int count = cmdline.Length; + + System.Console.Write(" "); + while (count-- > 0) + System.Console.Write(" "); + + System.Console.CursorTop = y; + System.Console.CursorLeft = 0; + } + WritePrefixLine(senderColor, sender); + WriteConsoleLine(color, format, args); + if (y != -1) + y = System.Console.CursorTop; + } } private void WriteNewLine(ConsoleColor color, string format, params object[] args) { + lock (cmdline) + { + if (y != -1) + { + System.Console.CursorTop = y; + System.Console.CursorLeft = 0; + + int count = cmdline.Length; + + System.Console.Write(" "); + while (count-- > 0) + System.Console.Write(" "); + + System.Console.CursorTop = y; + System.Console.CursorLeft = 0; + } + WriteConsoleLine(color, format, args); + if (y != -1) + y = System.Console.CursorTop; + } + } + + private void WriteConsoleLine(ConsoleColor color, string format, params object[] args) + { try { lock (m_syncRoot) @@ -240,108 +515,150 @@ namespace OpenSim.Framework.Console } } - public string ReadLine() + private void Help(string module, string[] cmd) { - try - { - string line = System.Console.ReadLine(); + List help = Commands.GetHelp(); + + foreach (string s in help) + Output(s); + } - while (line == null) + private void Show() + { + lock (cmdline) + { + if (y == -1 || System.Console.BufferWidth == 0) + return; + + int xc = prompt.Length + cp; + int new_x = xc % System.Console.BufferWidth; + int new_y = y + xc / System.Console.BufferWidth; + int end_y = y + (cmdline.Length + prompt.Length) / System.Console.BufferWidth; + if (end_y / System.Console.BufferWidth >= h) + h++; + if (end_y >= System.Console.BufferHeight) // wrap { - line = System.Console.ReadLine(); + y--; + new_y--; + System.Console.CursorLeft = 0; + System.Console.CursorTop = System.Console.BufferHeight-1; + System.Console.WriteLine(" "); } - return line; - } - catch (Exception e) - { - m_log.Error("[Console]: System.Console.ReadLine exception " + e.ToString()); - return String.Empty; - } - } + System.Console.CursorTop = y; + System.Console.CursorLeft = 0; - public int Read() - { - return System.Console.Read(); + if (echo) + System.Console.Write("{0}{1}", prompt, cmdline); + else + System.Console.Write("{0}", prompt); + + System.Console.CursorLeft = new_x; + System.Console.CursorTop = new_y; + } } - public IPAddress CmdPromptIPAddress(string prompt, string defaultvalue) + public void LockOutput() { - IPAddress address; - string addressStr; - - while (true) + System.Threading.Monitor.Enter(cmdline); + try { - addressStr = CmdPrompt(prompt, defaultvalue); - if (IPAddress.TryParse(addressStr, out address)) + if (y != -1) { - break; - } - else - { - m_log.Error("Illegal address. Please re-enter."); + System.Console.CursorTop = y; + System.Console.CursorLeft = 0; + + int count = cmdline.Length + prompt.Length; + + while (count-- > 0) + System.Console.Write(" "); + + System.Console.CursorTop = y; + System.Console.CursorLeft = 0; + } } - - return address; + catch (Exception) + { + } } - public uint CmdPromptIPPort(string prompt, string defaultvalue) + public void UnlockOutput() { - uint port; - string portStr; + if (y != -1) + { + y = System.Console.CursorTop; + Show(); + } + System.Threading.Monitor.Exit(cmdline); + } - while (true) + public void Output(string text) + { + lock (cmdline) { - portStr = CmdPrompt(prompt, defaultvalue); - if (uint.TryParse(portStr, out port)) + if (y == -1) { - if (port >= IPEndPoint.MinPort && port <= IPEndPoint.MaxPort) - { - break; - } + System.Console.WriteLine(text); + + return; } - m_log.Error("Illegal address. Please re-enter."); - } + System.Console.CursorTop = y; + System.Console.CursorLeft = 0; - return port; - } + int count = cmdline.Length + prompt.Length; - // Displays a prompt and waits for the user to enter a string, then returns that string - // (Done with no echo and suitable for passwords - currently disabled) - public string PasswdPrompt(string prompt) - { - // FIXME: Needs to be better abstracted - System.Console.WriteLine(String.Format("{0}: ", prompt)); - //ConsoleColor oldfg = System.Console.ForegroundColor; - //System.Console.ForegroundColor = System.Console.BackgroundColor; - string temp = System.Console.ReadLine(); - //System.Console.ForegroundColor = oldfg; - return temp; + while (count-- > 0) + System.Console.Write(" "); + + System.Console.CursorTop = y; + System.Console.CursorLeft = 0; + + System.Console.WriteLine(text); + + y = System.Console.CursorTop; + + Show(); + } } - // Displays a command prompt and waits for the user to enter a string, then returns that string - public string CmdPrompt(string prompt) + private void ContextHelp() { - System.Console.WriteLine(String.Format("{0}: ", prompt)); - return ReadLine(); + string[] words = Parser.Parse(cmdline.ToString()); + + string[] opts = Commands.FindNextOption(words, cmdline.ToString().EndsWith(" ")); + + if (opts[0].StartsWith("Command help:")) + Output(opts[0]); + else + Output(String.Format("Options: {0}", String.Join(" ", opts))); } - // Displays a command prompt and returns a default value if the user simply presses enter - public string CmdPrompt(string prompt, string defaultresponse) + public void Prompt() { - string temp = CmdPrompt(String.Format("{0} [{1}]", prompt, defaultresponse)); - if (temp == String.Empty) - { - return defaultresponse; - } - else + string line = ReadLine(m_defaultPrompt, true, true); + + if (line != String.Empty) { - return temp; + m_log.Info("Invalid command"); } } + public string CmdPrompt(string p) + { + return ReadLine(String.Format("{0}: ", p), false, true); + } + + public string CmdPrompt(string p, string def) + { + string ret = ReadLine(String.Format("{0} [{1}]: ", p, def), false, true); + if (ret == String.Empty) + ret = def; + + return ret; + } + // Displays a command prompt and returns a default value, user may only enter 1 of 2 options public string CmdPrompt(string prompt, string defaultresponse, string OptionA, string OptionB) { @@ -362,85 +679,137 @@ namespace OpenSim.Framework.Console return temp; } - // Runs a command with a number of parameters - public Object RunCmd(string Cmd, string[] cmdparams) - { - m_cmdParser.RunCmd(Cmd, cmdparams); - return null; - } - - // Shows data about something - public void ShowCommands(string ShowWhat) + // Displays a prompt and waits for the user to enter a string, then returns that string + // (Done with no echo and suitable for passwords) + public string PasswdPrompt(string p) { - m_cmdParser.Show(new string[] { ShowWhat }); + return ReadLine(p, false, false); } - public void Prompt() + public void RunCommand(string cmd) { - string tempstr = CmdPrompt(m_defaultPrompt); - RunCommand(tempstr); + string[] parts = Parser.Parse(cmd); + Commands.Resolve(parts); } - public void RunCommand(string cmdline) + public string ReadLine(string p, bool isCommand, bool e) { - Regex Extractor = new Regex(@"(['""][^""]+['""])\s*|([^\s]+)\s*", RegexOptions.Compiled); - char[] delims = {' ', '"'}; - MatchCollection matches = Extractor.Matches(cmdline); - // Get matches + h = 1; + cp = 0; + prompt = p; + echo = e; + int historyLine = history.Count; - if (matches.Count == 0) - return; + System.Console.CursorLeft = 0; // Needed for mono + System.Console.Write(" "); // Needed for mono - string cmd = matches[0].Value.Trim(delims); - string[] cmdparams = new string[matches.Count - 1]; + y = System.Console.CursorTop; + cmdline = new StringBuilder(); - for (int i = 1; i < matches.Count; i++) + while(true) { - cmdparams[i-1] = matches[i].Value.Trim(delims); - } + Show(); - try - { - RunCmd(cmd, cmdparams); - } - catch (Exception e) - { - m_log.ErrorFormat("[Console]: Command [{0}] failed with exception {1}", cmdline, e.ToString()); - m_log.Error(e.StackTrace); - } - } + ConsoleKeyInfo key = System.Console.ReadKey(true); + char c = key.KeyChar; - public string LineInfo - { - get - { - string result = String.Empty; + if (!Char.IsControl(c)) + { + if (cp >= 318) + continue; - string stacktrace = Environment.StackTrace; - List lines = new List(stacktrace.Split(new string[] {"at "}, StringSplitOptions.None)); + if (c == '?' && isCommand) + { + ContextHelp(); + continue; + } - if (lines.Count > 4) + cmdline.Insert(cp, c); + cp++; + } + else { - lines.RemoveRange(0, 4); + switch (key.Key) + { + case ConsoleKey.Backspace: + if (cp == 0) + break; + cmdline.Remove(cp-1, 1); + cp--; - string tmpLine = lines[0]; + System.Console.CursorLeft = 0; + System.Console.CursorTop = y; - int inIndex = tmpLine.IndexOf(" in "); + System.Console.Write("{0}{1} ", prompt, cmdline); - if (inIndex > -1) - { - result = tmpLine.Substring(0, inIndex); + break; + case ConsoleKey.End: + cp = cmdline.Length; + break; + case ConsoleKey.Home: + cp = 0; + break; + case ConsoleKey.UpArrow: + if (historyLine < 1) + break; + historyLine--; + LockOutput(); + cmdline = new StringBuilder(history[historyLine]); + cp = cmdline.Length; + UnlockOutput(); + break; + case ConsoleKey.DownArrow: + if (historyLine >= history.Count) + break; + historyLine++; + LockOutput(); + if (historyLine == history.Count) + cmdline = new StringBuilder(); + else + cmdline = new StringBuilder(history[historyLine]); + cp = cmdline.Length; + UnlockOutput(); + break; + case ConsoleKey.LeftArrow: + if (cp > 0) + cp--; + break; + case ConsoleKey.RightArrow: + if (cp < cmdline.Length) + cp++; + break; + case ConsoleKey.Enter: + System.Console.CursorLeft = 0; + System.Console.CursorTop = y; + + System.Console.WriteLine("{0}{1}", prompt, cmdline); - int lineIndex = tmpLine.IndexOf(":line "); + y = -1; - if (lineIndex > -1) + if (isCommand) { - lineIndex += 6; - result += ", line " + tmpLine.Substring(lineIndex, (tmpLine.Length - lineIndex) - 5); + string[] cmd = Commands.Resolve(Parser.Parse(cmdline.ToString())); + + if (cmd.Length != 0) + { + int i; + + for (i=0 ; i < cmd.Length ; i++) + { + if (cmd[i].Contains(" ")) + cmd[i] = "\"" + cmd[i] + "\""; + } + AddToHistory(String.Join(" ", cmd)); + return String.Empty; + } } + + AddToHistory(cmdline.ToString()); + return cmdline.ToString(); + default: + break; } } - return result; } } } diff --git a/OpenSim/Framework/Console/ConsoleCallbacksBase.cs b/OpenSim/Framework/Console/ConsoleCallbacksBase.cs deleted file mode 100644 index d37c47a..0000000 --- a/OpenSim/Framework/Console/ConsoleCallbacksBase.cs +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * 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 OpenSim Project 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 DEVELOPERS ``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 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. - */ - -namespace OpenSim.Framework.Console -{ - public interface conscmd_callback - { - void RunCmd(string cmd, string[] cmdparams); - void Show(string[] showParams); - } -} diff --git a/OpenSim/Framework/Console/OpenSimAppender.cs b/OpenSim/Framework/Console/OpenSimAppender.cs index b07617f..6193bac 100644 --- a/OpenSim/Framework/Console/OpenSimAppender.cs +++ b/OpenSim/Framework/Console/OpenSimAppender.cs @@ -37,6 +37,14 @@ namespace OpenSim.Framework.Console /// public class OpenSimAppender : AnsiColorTerminalAppender { + private ConsoleBase m_console = null; + + public ConsoleBase Console + { + get { return m_console; } + set { m_console = value; } + } + private static readonly ConsoleColor[] Colors = { // the dark colors don't seem to be visible on some black background terminals like putty :( //ConsoleColor.DarkBlue, @@ -55,6 +63,9 @@ namespace OpenSim.Framework.Console override protected void Append(LoggingEvent le) { + if (m_console != null) + m_console.LockOutput(); + try { string loggingMessage = RenderLoggingEvent(le); @@ -96,6 +107,11 @@ namespace OpenSim.Framework.Console { System.Console.WriteLine("Couldn't write out log message: {0}", e.ToString()); } + finally + { + if (m_console != null) + m_console.UnlockOutput(); + } } private void WriteColorText(ConsoleColor color, string sender) diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs index ce74b46..493c626 100644 --- a/OpenSim/Framework/IScene.cs +++ b/OpenSim/Framework/IScene.cs @@ -27,6 +27,7 @@ using System.Collections.Generic; using OpenMetaverse; +using OpenSim.Framework.Console; namespace OpenSim.Framework { @@ -88,5 +89,7 @@ namespace OpenSim.Framework T RequestModuleInterface(); T[] RequestModuleInterfaces(); + + void AddCommand(string module, string command, string shorthelp, string longhelp, CommandDelegate callback); } } diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 473991a..cc75df4 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -98,7 +98,45 @@ namespace OpenSim.Framework.Servers /// /// Must be overriden by child classes for their own server specific startup behaviour. /// - protected abstract void StartupSpecific(); + protected virtual void StartupSpecific() + { + if (m_console != null) + { + SetConsoleLogLevel(new string[] { "ALL" }); + + m_console.Commands.AddCommand("base", "quit", + "quit", + "Quit the application", HandleQuit); + + m_console.Commands.AddCommand("base", "shutdown", + "shutdown", + "Quit the application", HandleQuit); + + m_console.Commands.AddCommand("base", "set log level", + "set log level ", + "Set the console logging level", HandleLogLevel); + + m_console.Commands.AddCommand("base", "show info", + "show info", + "Show general information", HandleShow); + + m_console.Commands.AddCommand("base", "show stats", + "show stats", + "Show statistics", HandleShow); + + m_console.Commands.AddCommand("base", "show threads", + "show threads", + "Show thread status", HandleShow); + + m_console.Commands.AddCommand("base", "show uptime", + "show uptime", + "Show server uptime", HandleShow); + + m_console.Commands.AddCommand("base", "show version", + "show version", + "Show server version", HandleShow); + } + } /// /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing @@ -212,6 +250,8 @@ namespace OpenSim.Framework.Servers return; } + consoleAppender.Console = m_console; + if (setParams.Length > 0) { Level consoleLevel = repository.LevelMap[setParams[0]]; @@ -261,56 +301,18 @@ namespace OpenSim.Framework.Servers Environment.Exit(0); } - /// - /// Runs commands issued by the server console from the operator - /// - /// The first argument of the parameter (the command) - /// Additional arguments passed to the command - public virtual void RunCmd(string command, string[] cmdparams) + private void HandleQuit(string module, string[] args) { - switch (command) - { - case "help": - ShowHelp(cmdparams); - Notice(""); - break; - - case "set": - Set(cmdparams); - break; - - case "show": - if (cmdparams.Length > 0) - { - Show(cmdparams); - } - break; - - case "quit": - case "shutdown": - Shutdown(); - break; - } + Shutdown(); } - /// - /// Set an OpenSim parameter - /// - /// - /// The arguments given to the set command. - /// - public virtual void Set(string[] setArgs) + private void HandleLogLevel(string module, string[] cmd) { - // Temporary while we only have one command which takes at least two parameters - if (setArgs.Length < 2) - return; - - if (setArgs[0] == "log" && setArgs[1] == "level") + if (cmd.Length > 3) { - string[] setParams = new string[setArgs.Length - 2]; - Array.Copy(setArgs, 2, setParams, 0, setArgs.Length - 2); + string level = cmd[3]; - SetConsoleLogLevel(setParams); + SetConsoleLogLevel(new string[] { level }); } } @@ -324,18 +326,6 @@ namespace OpenSim.Framework.Servers if (helpArgs.Length == 0) { - List helpTopics = GetHelpTopics(); - - if (helpTopics.Count > 0) - { - Notice( - "As well as the help information below, you can also type help to get more information on the following areas:"); - Notice(string.Format(" {0}", string.Join(", ", helpTopics.ToArray()))); - Notice(""); - } - - Notice("quit - equivalent to shutdown."); - Notice("set log level [level] - change the console logging level only. For example, off or debug."); Notice("show info - show server information (e.g. startup path)."); @@ -345,21 +335,20 @@ namespace OpenSim.Framework.Servers Notice("show threads - list tracked threads"); Notice("show uptime - show server startup time and uptime."); Notice("show version - show server version."); - Notice("shutdown - shutdown the server."); Notice(""); return; } } - /// - /// Outputs to the console information about the region - /// - /// - /// What information to display (valid arguments are "uptime", "users", ...) - /// - public virtual void Show(string[] showParams) + public virtual void HandleShow(string module, string[] cmd) { + List args = new List(cmd); + + args.RemoveAt(0); + + string[] showParams = args.ToArray(); + switch (showParams[0]) { case "info": diff --git a/OpenSim/Grid/AssetServer/Main.cs b/OpenSim/Grid/AssetServer/Main.cs index 060c473..c71e53f 100644 --- a/OpenSim/Grid/AssetServer/Main.cs +++ b/OpenSim/Grid/AssetServer/Main.cs @@ -43,7 +43,7 @@ namespace OpenSim.Grid.AssetServer /// /// An asset server /// - public class OpenAsset_Main : BaseOpenSimServer, conscmd_callback + public class OpenAsset_Main : BaseOpenSimServer { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -76,7 +76,7 @@ namespace OpenSim.Grid.AssetServer public OpenAsset_Main() { - m_console = new ConsoleBase("Asset", this); + m_console = new ConsoleBase("Asset"); MainConsole.Instance = m_console; } @@ -99,6 +99,8 @@ namespace OpenSim.Grid.AssetServer AddHttpHandlers(); m_httpServer.Start(); + + base.StartupSpecific(); } protected void AddHttpHandlers() diff --git a/OpenSim/Grid/GridServer/GridServerBase.cs b/OpenSim/Grid/GridServer/GridServerBase.cs index 68edbd2..3fb07b5 100644 --- a/OpenSim/Grid/GridServer/GridServerBase.cs +++ b/OpenSim/Grid/GridServer/GridServerBase.cs @@ -39,7 +39,7 @@ namespace OpenSim.Grid.GridServer { /// /// - public class GridServerBase : BaseOpenSimServer, conscmd_callback + public class GridServerBase : BaseOpenSimServer { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -59,43 +59,34 @@ namespace OpenSim.Grid.GridServer public GridServerBase() { - m_console = new ConsoleBase("Grid", this); + m_console = new ConsoleBase("Grid"); MainConsole.Instance = m_console; } - public override void RunCmd(string cmd, string[] cmdparams) + private void HandleRegistration(string module, string[] cmd) { - base.RunCmd(cmd, cmdparams); - - switch (cmd) + switch (cmd[0]) { - case "disable-reg": - m_config.AllowRegionRegistration = false; - m_log.Info("Region registration disabled"); - break; - case "enable-reg": - m_config.AllowRegionRegistration = true; - m_log.Info("Region registration enabled"); - break; + case "enable": + m_config.AllowRegionRegistration = true; + m_log.Info("Region registration enabled"); + break; + case "disable": + m_config.AllowRegionRegistration = false; + m_log.Info("Region registration disabled"); + break; } } - - public override void Show(string[] showParams) - { - base.Show(showParams); - switch (showParams[0]) + private void HandleShowStatus(string module, string[] cmd) + { + if (m_config.AllowRegionRegistration) { - case "status": - if (m_config.AllowRegionRegistration) - { - m_log.Info("Region registration enabled."); - } - else - { - m_log.Info("Region registration disabled."); - } - break; + m_log.Info("Region registration enabled."); + } + else + { + m_log.Info("Region registration disabled."); } } @@ -120,6 +111,20 @@ namespace OpenSim.Grid.GridServer // Timer simCheckTimer = new Timer(3600000 * 3); // 3 Hours between updates. // simCheckTimer.Elapsed += new ElapsedEventHandler(CheckSims); // simCheckTimer.Enabled = true; + + base.StartupSpecific(); + + m_console.Commands.AddCommand("gridserver", "enable registration", + "enable registration", + "Enable new regions to register", HandleRegistration); + + m_console.Commands.AddCommand("gridserver", "disable registration", + "disable registration", + "Disable registering new regions", HandleRegistration); + + m_console.Commands.AddCommand("gridserver", "show status", + "show status", + "Show registration status", HandleShowStatus); } protected void AddHttpHandlers() diff --git a/OpenSim/Grid/InventoryServer/Main.cs b/OpenSim/Grid/InventoryServer/Main.cs index 81a6a03..4727f6e 100644 --- a/OpenSim/Grid/InventoryServer/Main.cs +++ b/OpenSim/Grid/InventoryServer/Main.cs @@ -38,7 +38,7 @@ using OpenSim.Framework.Servers; namespace OpenSim.Grid.InventoryServer { - public class OpenInventory_Main : BaseOpenSimServer, conscmd_callback + public class OpenInventory_Main : BaseOpenSimServer { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -58,7 +58,7 @@ namespace OpenSim.Grid.InventoryServer public OpenInventory_Main() { - m_console = new ConsoleBase("Inventory", this); + m_console = new ConsoleBase("Inventory"); MainConsole.Instance = m_console; } @@ -77,6 +77,12 @@ namespace OpenSim.Grid.InventoryServer m_httpServer.Start(); m_log.Info("[" + LogName + "]: Started HTTP server"); + + base.StartupSpecific(); + + m_console.Commands.AddCommand("inventoryserver", "add user", + "add user", + "Add a random user inventory", HandleAddUser); } protected void AddHttpHandlers() @@ -146,16 +152,9 @@ namespace OpenSim.Grid.InventoryServer } } - public override void RunCmd(string cmd, string[] cmdparams) + private void HandleAddUser(string module, string[] args) { - base.RunCmd(cmd, cmdparams); - - switch (cmd) - { - case "add-user": - m_inventoryService.CreateUsersInventory(UUID.Random().Guid); - break; - } + m_inventoryService.CreateUsersInventory(UUID.Random().Guid); } } } diff --git a/OpenSim/Grid/MessagingServer/Main.cs b/OpenSim/Grid/MessagingServer/Main.cs index e83da7a..9b7e731 100644 --- a/OpenSim/Grid/MessagingServer/Main.cs +++ b/OpenSim/Grid/MessagingServer/Main.cs @@ -41,7 +41,7 @@ namespace OpenSim.Grid.MessagingServer { /// /// - public class OpenMessage_Main : BaseOpenSimServer, conscmd_callback + public class OpenMessage_Main : BaseOpenSimServer { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -64,7 +64,7 @@ namespace OpenSim.Grid.MessagingServer public OpenMessage_Main() { - m_console = new ConsoleBase("Messaging", this); + m_console = new ConsoleBase("Messaging"); MainConsole.Instance = m_console; } @@ -124,6 +124,16 @@ namespace OpenSim.Grid.MessagingServer registerWithUserServer(); m_log.Info("[SERVER]: Messageserver 0.5 - Startup complete"); + + base.StartupSpecific(); + + m_console.Commands.AddCommand("messageserver", "clear cache", + "clear cache", + "Clear presence cache", HandleClearCache); + + m_console.Commands.AddCommand("messageserver", "register", + "register", + "Re-register with user server(s)", HandleRegister); } public void do_create(string what) @@ -154,29 +164,17 @@ namespace OpenSim.Grid.MessagingServer } } - public override void RunCmd(string cmd, string[] cmdparams) + private void HandleClearCache(string module, string[] cmd) { - base.RunCmd(cmd, cmdparams); - - switch (cmd) - { - case "clear-cache": - int entries = msgsvc.ClearRegionCache(); - m_console.Notice("Region cache cleared! Cleared " + entries.ToString() + " entries"); - break; - case "register": - deregisterFromUserServer(); - registerWithUserServer(); - break; - } + int entries = msgsvc.ClearRegionCache(); + m_console.Notice("Region cache cleared! Cleared " + + entries.ToString() + " entries"); } - - protected override void ShowHelp(string[] helpArgs) + + private void HandleRegister(string module, string[] cmd) { - base.ShowHelp(helpArgs); - - m_console.Notice("clear-cache - Clears region cache. Should be done when regions change position. The region cache gets stale after a while."); - m_console.Notice("register - (Re-)registers with user-server. This might be necessary if the userserver crashed/restarted"); + deregisterFromUserServer(); + registerWithUserServer(); } public override void ShutdownSpecific() diff --git a/OpenSim/Grid/UserServer/Main.cs b/OpenSim/Grid/UserServer/Main.cs index be26ab3..0b0bee1 100644 --- a/OpenSim/Grid/UserServer/Main.cs +++ b/OpenSim/Grid/UserServer/Main.cs @@ -46,7 +46,7 @@ namespace OpenSim.Grid.UserServer /// /// Grid user server main class /// - public class OpenUser_Main : BaseOpenSimServer, conscmd_callback + public class OpenUser_Main : BaseOpenSimServer { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -73,7 +73,7 @@ namespace OpenSim.Grid.UserServer public OpenUser_Main() { - m_console = new ConsoleBase("User", this); + m_console = new ConsoleBase("User"); MainConsole.Instance = m_console; } @@ -119,6 +119,37 @@ namespace OpenSim.Grid.UserServer m_httpServer = new BaseHttpServer(Cfg.HttpPort); AddHttpHandlers(); m_httpServer.Start(); + + base.StartupSpecific(); + + m_console.Commands.AddCommand("userserver", "create user", + "create user [ [ [ [email]]]]", + "Create a new user account", RunCommand); + + m_console.Commands.AddCommand("userserver", "reset user password", + "reset user password [ [ []]]", + "Reset a user's password", RunCommand); + + m_console.Commands.AddCommand("userserver", "login level", + "login level ", + "Set the minimum user level to log in", HandleLoginCommand); + + m_console.Commands.AddCommand("userserver", "login reset", + "login reset", + "Reset the login level to allow all users", + HandleLoginCommand); + + m_console.Commands.AddCommand("userserver", "login text", + "login text ", + "Set the text users will see on login", HandleLoginCommand); + + m_console.Commands.AddCommand("userserver", "test-inventory", + "test-inventory", + "Perform a test inventory transaction", RunCommand); + + m_console.Commands.AddCommand("userserver", "logoff-user", + "logoff-user ", + "Log off a named user", RunCommand); } /// @@ -301,39 +332,54 @@ namespace OpenSim.Grid.UserServer m_userManager.ResetUserPassword(firstName, lastName, newPassword); } - public override void RunCmd(string cmd, string[] cmdparams) + private void HandleLoginCommand(string module, string[] cmd) { - base.RunCmd(cmd, cmdparams); - switch (cmd) + string subcommand = cmd[1]; + + switch (subcommand) { - case "create": - do_create(cmdparams); - break; - - case "reset": - Reset(cmdparams); - break; - - - case "login-level": - // Set the minimal level to allow login - // Usefull to allow grid update without worrying about users. - // or fixing critical issue - if (cmdparams.Length == 1) + case "level": + // Set the minimal level to allow login + // Useful to allow grid update without worrying about users. + // or fixing critical issues + // + if (cmd.Length > 2) { - int level = Convert.ToInt32(cmdparams[0]); + int level = Convert.ToInt32(cmd[2]); m_loginService.setloginlevel(level); } break; - case "login-reset": + case "reset": m_loginService.setloginlevel(0); break; - case "login-text": - if (cmdparams.Length == 1) + case "text": + if (cmd.Length > 2) { - m_loginService.setwelcometext(cmdparams[0]); + m_loginService.setwelcometext(cmd[2]); } break; + } + } + + public void RunCommand(string module, string[] cmd) + { + List args = new List(cmd); + string command = cmd[0]; + + args.RemoveAt(0); + + string[] cmdparams = args.ToArray(); + + switch (command) + { + case "create": + do_create(cmdparams); + break; + + case "reset": + Reset(cmdparams); + break; + case "test-inventory": // RestObjectPosterResponse> requester = new RestObjectPosterResponse>(); diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs index a8e1499..7a427dc 100644 --- a/OpenSim/Region/Application/Application.cs +++ b/OpenSim/Region/Application/Application.cs @@ -34,6 +34,7 @@ using log4net.Config; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Console; +using OpenSim.Region.Framework.Scenes; namespace OpenSim { @@ -46,6 +47,8 @@ namespace OpenSim public static bool m_saveCrashDumps = false; public static string m_crashDir = "crashes"; + protected static OpenSimBase m_sim = null; + //could move our main function into OpenSimMain and kill this class public static void Main(string[] args) { @@ -93,18 +96,18 @@ namespace OpenSim if (background) { - OpenSimBase sim = new OpenSimBackground(configSource); - sim.Startup(); + m_sim = new OpenSimBackground(configSource); + m_sim.Startup(); } else { - OpenSimBase sim = null; + m_sim = null; if (hgrid) - sim = new HGOpenSimNode(configSource); + m_sim = new HGOpenSimNode(configSource); else - sim = new OpenSim(configSource); + m_sim = new OpenSim(configSource); - sim.Startup(); + m_sim.Startup(); while (true) { diff --git a/OpenSim/Region/Application/HGOpenSimNode.cs b/OpenSim/Region/Application/HGOpenSimNode.cs index 4941fb4..2de9ddf 100644 --- a/OpenSim/Region/Application/HGOpenSimNode.cs +++ b/OpenSim/Region/Application/HGOpenSimNode.cs @@ -77,6 +77,9 @@ namespace OpenSim m_log.Info("===================================================================="); base.StartupSpecific(); + + MainConsole.Instance.Commands.AddCommand("hypergrid", "link-mapping", "link-mapping [ ] ", "Set local coordinate to map HG regions to", RunCommand); + MainConsole.Instance.Commands.AddCommand("hypergrid", "link-region", "link-region ", "Link a hypergrid region", RunCommand); } protected override void InitialiseStandaloneServices(LibraryRootFolder libraryRootFolder) @@ -143,11 +146,18 @@ namespace OpenSim m_configSettings.See_into_region_from_neighbor, m_config.Source, m_version); } - public override void RunCmd(string command, string[] cmdparams) + public void RunCommand(string module, string[] cp) { + List cmdparams = new List(cp); + if (cmdparams.Count < 1) + return; + + string command = cmdparams[0]; + cmdparams.RemoveAt(0); + if (command.Equals("link-mapping")) { - if (cmdparams.Length == 2) + if (cmdparams.Count == 2) { try { @@ -166,11 +176,11 @@ namespace OpenSim else if (command.Equals("link-region")) { // link-region - if (cmdparams.Length < 4) + if (cmdparams.Count < 4) { - if ((cmdparams.Length == 1) || (cmdparams.Length ==2)) + if ((cmdparams.Count == 1) || (cmdparams.Count ==2)) { - LoadXmlLinkFile(cmdparams); + LoadXmlLinkFile(cmdparams.ToArray()); } else { @@ -201,19 +211,16 @@ namespace OpenSim if (TryCreateLink(xloc, yloc, externalPort, externalHostName, out regInfo)) { - if (cmdparams.Length >= 5) + if (cmdparams.Count >= 5) { regInfo.RegionName = ""; - for (int i = 4; i < cmdparams.Length; i++) + for (int i = 4; i < cmdparams.Count; i++) regInfo.RegionName += cmdparams[i] + " "; } } return; } - - base.RunCmd(command, cmdparams); - } private void LoadXmlLinkFile(string[] cmdparams) diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index af42a3d..37066c2 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -49,7 +49,7 @@ namespace OpenSim /// /// Interactive OpenSim region server /// - public class OpenSim : OpenSimBase, conscmd_callback + public class OpenSim : OpenSimBase { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -59,11 +59,6 @@ namespace OpenSim private string m_timedScript = "disabled"; private Timer m_scriptTimer; - /// - /// List of Console Plugin Commands - /// - private static List m_PluginCommandInfos = new List(); - public OpenSim(IConfigSource configSource) : base(configSource) { } @@ -97,9 +92,189 @@ namespace OpenSim //GCSettings.LatencyMode = GCLatencyMode.Batch; //m_log.InfoFormat("[OPENSIM MAIN]: GC Latency Mode: {0}", GCSettings.LatencyMode.ToString()); - m_console = new ConsoleBase("Region", this); + m_console = new ConsoleBase("Region"); MainConsole.Instance = m_console; + m_console.Commands.AddCommand("region", "clear assets", + "clear assets", + "Clear the asset cache", HandleClearAssets); + + m_console.Commands.AddCommand("region", "force update", + "force update", + "Force the update of all objects on clients", + HandleForceUpdate); + + m_console.Commands.AddCommand("region", "debug packet", + "debug packet ", + "Turn on packet debugging", Debug); + + m_console.Commands.AddCommand("region", "debug scene", + "debug scene ", + "Turn on scene debugging", Debug); + + m_console.Commands.AddCommand("region", "change region", + "change region ", + "Change current console region", ChangeSelectedRegion); + + m_console.Commands.AddCommand("region", "save xml", + "save xml", + "Save a region's data in XML format", SaveXml); + + m_console.Commands.AddCommand("region", "save xml2", + "save xml2", + "Save a region's data in XML2 format", SaveXml2); + + m_console.Commands.AddCommand("region", "load xml", + "load xml [-newIDs [ ]]", + "Load a region's data from XML format", LoadXml); + + m_console.Commands.AddCommand("region", "load xml2", + "load xml2", + "Load a region's data from XML2 format", LoadXml2); + + m_console.Commands.AddCommand("region", "save prims xml2", + "save prims xml2 [ ]", + "Save named prim to XML2", SavePrimsXml2); + + m_console.Commands.AddCommand("region", "load oar", + "load oar ", + "Load a region's data from OAR archive", LoadOar); + + m_console.Commands.AddCommand("region", "save oar", + "save oar ", + "Save a region's data to an OAR archive", SaveOar); + + m_console.Commands.AddCommand("region", "save inventory", + "save inventory ", + "Save user inventory data", SaveInv); + + m_console.Commands.AddCommand("region", "load inventory", + "load inventory ", + "Load user inventory data", LoadInv); + + m_console.Commands.AddCommand("region", "edit scale", + "edit scale ", + "Change the scale of a named prim", HandleEditScale); + + m_console.Commands.AddCommand("region", "kick user", + "kick user ", + "Kick a user off the simulator", HandleEditScale); + + m_console.Commands.AddCommand("region", "show assets", + "show assets", + "Show asset data", HandleShow); + + m_console.Commands.AddCommand("region", "show users", + "show users [full]", + "Show user data", HandleShow); + + m_console.Commands.AddCommand("region", "show users full", + "show users full", + String.Empty, HandleShow); + + m_console.Commands.AddCommand("region", "show modules", + "show modules", + "Show module data", HandleShow); + + m_console.Commands.AddCommand("region", "show regions", + "show regions", + "Show region data", HandleShow); + + m_console.Commands.AddCommand("region", "show queues", + "show queues", + "Show queue data", HandleShow); + + m_console.Commands.AddCommand("region", "alert", + "alert ", + "Send an alert to a user", RunCommand); + + m_console.Commands.AddCommand("region", "alert general", + "alert general ", + "Send an alert everyone", RunCommand); + + m_console.Commands.AddCommand("region", "backup", + "backup", + "Persist objects to the database now", RunCommand); + + m_console.Commands.AddCommand("region", "create region", + "create region", + "Create a new region", HandleCreateRegion); + + m_console.Commands.AddCommand("region", "login enable", + "login enable", + "Enable logins to the simulator", HandleLoginEnable); + + m_console.Commands.AddCommand("region", "login disable", + "login disable", + "Disable logins to the simulator", HandleLoginDisable); + + m_console.Commands.AddCommand("region", "login status", + "login status", + "Display status of logins", HandleLoginStatus); + + m_console.Commands.AddCommand("region", "restart", + "restart", + "Restart all sims in this instance", RunCommand); + + m_console.Commands.AddCommand("region", "config set", + "config set
", + "Set a config option", HandleConfig); + + m_console.Commands.AddCommand("region", "config get", + "config get
", + "Read a config option", HandleConfig); + + m_console.Commands.AddCommand("region", "config save", + "config save", + "Save current configuration", HandleConfig); + + m_console.Commands.AddCommand("region", "command-script", + "command-script