From f2cbc48a9e704da8e86ed659437c1e338e212c50 Mon Sep 17 00:00:00 2001
From: Tedd Hansen
Date: Sat, 6 Dec 2008 03:28:34 +0000
Subject: GUI for launching grids. Early version, but should work fine. Will
execute all OpenSim services redirect their input/output/errors to the
selected "GUI module". This version has following "GUI modules": * Windows
Forms * Windows Service (doesn't work yet) * Console * TCP daemon
This means that OpenSim can now run in a single console for those who want that.
Console functionallity is not too rich yet, but code/framework is there... more to come. :)
---
OpenSim/Tools/OpenSim.GridLaunch/App.config | 40 +
OpenSim/Tools/OpenSim.GridLaunch/AppExecutor.cs | 247 ++++++
.../OpenSim.GridLaunch/AppExecutor_AsyncIO.cs | 85 ++
.../Tools/OpenSim.GridLaunch/AppExecutor_Thread.cs | 187 +++++
.../Tools/OpenSim.GridLaunch/CommandProcessor.cs | 76 ++
.../OpenSim.GridLaunch/GUI/Console/Console.cs | 122 +++
OpenSim/Tools/OpenSim.GridLaunch/GUI/IGUI.cs | 12 +
.../Tools/OpenSim.GridLaunch/GUI/Network/Client.cs | 113 +++
.../Tools/OpenSim.GridLaunch/GUI/Network/TCPD.cs | 231 ++++++
.../OpenSim.GridLaunch/GUI/Service/Service.cs | 65 ++
.../GUI/WinForm/OpenSim Bottom Border.png | Bin 0 -> 163 bytes
.../GUI/WinForm/OpenSim Right Border.png | Bin 0 -> 545 bytes
.../OpenSim.GridLaunch/GUI/WinForm/OpenSim.png | Bin 0 -> 44571 bytes
.../GUI/WinForm/ProcessPanel.Designer.cs | 224 ++++++
.../OpenSim.GridLaunch/GUI/WinForm/ProcessPanel.cs | 288 +++++++
.../GUI/WinForm/ProcessPanel.resx | 882 +++++++++++++++++++++
.../GUI/WinForm/ucAppWindow.Designer.cs | 72 ++
.../OpenSim.GridLaunch/GUI/WinForm/ucAppWindow.cs | 63 ++
.../GUI/WinForm/ucAppWindow.resx | 120 +++
.../GUI/WinForm/ucInputField.Designer.cs | 77 ++
.../OpenSim.GridLaunch/GUI/WinForm/ucInputField.cs | 97 +++
.../GUI/WinForm/ucInputField.resx | 120 +++
.../GUI/WinForm/ucLogWindow.Designer.cs | 62 ++
.../OpenSim.GridLaunch/GUI/WinForm/ucLogWindow.cs | 54 ++
.../GUI/WinForm/ucLogWindow.resx | 120 +++
.../OpenSim.GridLaunch/OpenSim.GridLaunch.csproj | 126 +++
.../OpenSim.GridLaunch/OpenSim.GridLaunch.ini | 3 +
.../OpenSim.GridLaunch/OpenSim.GridLaunch.sln | 20 +
OpenSim/Tools/OpenSim.GridLaunch/Program.cs | 245 ++++++
.../OpenSim.GridLaunch/Properties/AssemblyInfo.cs | 63 ++
.../Properties/Resources.Designer.cs | 84 ++
.../OpenSim.GridLaunch/Properties/Resources.resx | 130 +++
OpenSim/Tools/OpenSim.GridLaunch/Settings.cs | 181 +++++
.../Tools/OpenSim.GridLaunch/log4netAppender.cs | 65 ++
34 files changed, 4274 insertions(+)
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/App.config
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/AppExecutor.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/AppExecutor_AsyncIO.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/AppExecutor_Thread.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/CommandProcessor.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/Console/Console.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/IGUI.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/Network/Client.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/Network/TCPD.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/Service/Service.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/OpenSim Bottom Border.png
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/OpenSim Right Border.png
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/OpenSim.png
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ProcessPanel.Designer.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ProcessPanel.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ProcessPanel.resx
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucAppWindow.Designer.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucAppWindow.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucAppWindow.resx
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucInputField.Designer.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucInputField.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucInputField.resx
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucLogWindow.Designer.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucLogWindow.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucLogWindow.resx
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/OpenSim.GridLaunch.csproj
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/OpenSim.GridLaunch.ini
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/OpenSim.GridLaunch.sln
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/Program.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/Properties/AssemblyInfo.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/Properties/Resources.Designer.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/Properties/Resources.resx
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/Settings.cs
create mode 100644 OpenSim/Tools/OpenSim.GridLaunch/log4netAppender.cs
(limited to 'OpenSim')
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/App.config b/OpenSim/Tools/OpenSim.GridLaunch/App.config
new file mode 100644
index 0000000..1e53319
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/App.config
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/AppExecutor.cs b/OpenSim/Tools/OpenSim.GridLaunch/AppExecutor.cs
new file mode 100644
index 0000000..2c6ac31
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/AppExecutor.cs
@@ -0,0 +1,247 @@
+/*
+ * 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.
+ */
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+using System.Text;
+using System.Threading;
+using log4net;
+
+namespace OpenSim.GridLaunch
+{
+ internal partial class AppExecutor : IDisposable
+ {
+ // How long to wait for process to shut down by itself
+ private static readonly int shutdownWaitSeconds = 10;
+
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ //private StreamWriter Input { get { return process.StandardInput; } }
+ //private StreamReader Output { get { return process.StandardOutput; } }
+ //private StreamReader Error { get { return process.StandardError; } }
+
+ private StreamWriter Input { get; set; }
+ private StreamReader Output { get; set; }
+ private StreamReader Error { get; set; }
+
+ private object processLock = new object();
+
+ private bool isRunning = false;
+ public bool IsRunning { get { return isRunning; } }
+
+ private string file;
+ public string File { get { return file; } }
+
+ Process process;
+
+ public AppExecutor(string File)
+ {
+ file = File;
+ }
+
+ #region Dispose of unmanaged resources
+ ~AppExecutor()
+ {
+ Dispose();
+ }
+ private bool isDisposed = false;
+ public void Dispose()
+ {
+ if (!isDisposed)
+ {
+ isDisposed = true;
+ Stop();
+ }
+ }
+ #endregion
+
+ #region Start / Stop process
+ public void Start()
+ {
+ if (isDisposed)
+ throw new ApplicationException("Attempt to start process in Disposed instance of AppExecutor.");
+ // Stop before starting
+ Stop();
+
+ lock (processLock)
+ {
+ isRunning = true;
+
+ m_log.InfoFormat("Starting \"{0}\".", file);
+
+ // Start the process
+ process = new Process();
+ process.StartInfo.FileName = file;
+ process.StartInfo.Arguments = "";
+ process.StartInfo.CreateNoWindow = true;
+ process.StartInfo.UseShellExecute = false;
+ process.StartInfo.ErrorDialog = false;
+ process.EnableRaisingEvents = true;
+
+
+ // Redirect all standard input/output/errors
+ process.StartInfo.RedirectStandardInput = true;
+ process.StartInfo.RedirectStandardOutput = true;
+ process.StartInfo.RedirectStandardError = true;
+
+ // Start process
+ process.Start();
+
+ Input = process.StandardInput;
+ Output = process.StandardOutput;
+ Error = process.StandardError;
+
+ // Start data copying
+ timer_Start();
+
+ // We will flush manually
+ //Input.AutoFlush = false;
+
+ }
+ }
+
+ public void Stop()
+ {
+ // Shut down process
+ // We will ignore some exceptions here, against good programming practice... :)
+
+ lock (processLock)
+ {
+ // Running?
+ if (!isRunning)
+ return;
+ isRunning = false;
+
+ timer_Stop();
+
+ m_log.InfoFormat("Stopping \"{0}\".", file);
+
+ // Send exit command to console
+ try
+ {
+ if (Input != null)
+ {
+ _writeLine("");
+ _writeLine("exit");
+ _writeLine("quit");
+ // Wait for process to exit
+ process.WaitForExit(1000 * shutdownWaitSeconds);
+ }
+ }
+ catch (Exception ex)
+ {
+ m_log.ErrorFormat("Exeption asking \"{0}\" to shut down: {1}", file, ex.ToString());
+ }
+
+ try
+ {
+ // Forcefully kill it
+ if (process.HasExited != true)
+ process.Kill();
+ }
+ catch (Exception ex)
+ {
+ m_log.ErrorFormat("Exeption killing \"{0}\": {1}", file, ex.ToString());
+ }
+
+ try
+ {
+ // Free resources
+ process.Close();
+ }
+ catch (Exception ex)
+ {
+ m_log.ErrorFormat("Exeption freeing resources for \"{0}\": {1}", file, ex.ToString());
+ }
+
+ // Dispose of stream and process object
+ //SafeDisposeOf(Input);
+ //SafeDisposeOf(Output);
+ //SafeDisposeOf(Error);
+ Program.SafeDisposeOf(process);
+ }
+
+ // Done stopping process
+ }
+
+ #endregion
+
+ #region Write to stdInput
+ public void Write(string Text)
+ {
+ // Lock so process won't shut down while we write, and that we won't write while proc is shutting down
+ lock (processLock)
+ {
+ _write(Text);
+ }
+ }
+ public void _write(string Text)
+ {
+ if (Input != null)
+ {
+ try
+ {
+ Input.Write(Text);
+ Input.Flush();
+ }
+ catch (Exception ex)
+ {
+ m_log.ErrorFormat("Exeption sending text \"{0}\" to \"{1}\": {2}", file, Text, ex.ToString());
+ }
+
+ }
+ }
+ public void WriteLine(string Text)
+ {
+ // Lock so process won't shut down while we write, and that we won't write while proc is shutting down
+ lock (processLock)
+ {
+ _writeLine(Text);
+ }
+ }
+ public void _writeLine(string Text)
+ {
+ if (Input != null)
+ {
+ try
+ {
+ m_log.DebugFormat("\"{0}\": Sending: \"{1}\"", file, Text);
+ Input.WriteLine(Text);
+ Input.Flush();
+ }
+ catch (Exception ex)
+ {
+ m_log.ErrorFormat("Exeption sending text \"{0}\" to \"{1}\": {2}", file, Text, ex.ToString());
+ }
+ }
+ }
+ #endregion
+
+ }
+}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/AppExecutor_AsyncIO.cs b/OpenSim/Tools/OpenSim.GridLaunch/AppExecutor_AsyncIO.cs
new file mode 100644
index 0000000..0d07226
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/AppExecutor_AsyncIO.cs
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace OpenSim.GridLaunch
+{
+ internal partial class AppExecutor
+ {
+
+
+ #region Start / Stop timer thread
+ private void timer_Start()
+ {
+ asyncReadOutput();
+ asyncReadError();
+ }
+
+ private bool running = true;
+ private void timer_Stop()
+ {
+ running = false;
+ }
+ #endregion
+
+ private byte[] readBufferOutput = new byte[4096];
+ private byte[] readBufferError = new byte[4096];
+
+ private void asyncReadOutput()
+ {
+ if (running)
+ Output.BaseStream.BeginRead(readBufferOutput, 0, readBufferOutput.Length, asyncReadCallBackOutput, null);
+ }
+ private void asyncReadError()
+ {
+ if (running)
+ Error.BaseStream.BeginRead(readBufferError, 0, readBufferError.Length, asyncReadCallBackError, null);
+ }
+
+ private void asyncReadCallBackOutput(IAsyncResult ar)
+ {
+ int len = Output.BaseStream.EndRead(ar);
+ Program.FireAppConsoleOutput(file,
+ System.Text.Encoding.ASCII.GetString(readBufferOutput, 0, len)
+ );
+
+ asyncReadOutput();
+ }
+ private void asyncReadCallBackError(IAsyncResult ar)
+ {
+ int len = Error.BaseStream.EndRead(ar);
+ Program.FireAppConsoleError(file,
+ System.Text.Encoding.ASCII.GetString(readBufferError, 0, len)
+ );
+
+ asyncReadError();
+ }
+ }
+}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/AppExecutor_Thread.cs b/OpenSim/Tools/OpenSim.GridLaunch/AppExecutor_Thread.cs
new file mode 100644
index 0000000..cd160f8
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/AppExecutor_Thread.cs
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+//using System;
+//using System.Collections;
+//using System.Collections.Generic;
+//using System.Reflection;
+//using System.Text;
+//using System.Threading;
+//using log4net;
+
+//namespace OpenSim.GridLaunch
+//{
+// internal class AppExecutor2
+// {
+// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+// private static readonly int consoleReadIntervalMilliseconds = 50;
+// //private static readonly Timer readTimer = new Timer(readConsole, null, Timeout.Infinite, Timeout.Infinite);
+// private static Thread timerThread;
+// private static object timerThreadLock = new object();
+
+// #region Start / Stop timer thread
+// private static void timer_Start()
+// {
+// //readTimer.Change(0, consoleReadIntervalMilliseconds);
+// lock (timerThreadLock)
+// {
+// if (timerThread == null)
+// {
+// m_log.Debug("Starting timer thread.");
+// timerThread = new Thread(timerThreadLoop);
+// timerThread.Name = "StdOutputStdErrorReadThread";
+// timerThread.IsBackground = true;
+// timerThread.Start();
+// }
+// }
+// }
+// private static void timer_Stop()
+// {
+// //readTimer.Change(Timeout.Infinite, Timeout.Infinite);
+// lock (timerThreadLock)
+// {
+// if (timerThread != null)
+// {
+// m_log.Debug("Stopping timer thread.");
+// try
+// {
+// if (timerThread.IsAlive)
+// timerThread.Abort();
+// timerThread.Join(2000);
+// timerThread = null;
+// }
+// catch (Exception ex)
+// {
+// m_log.Error("Exception stopping timer thread: " + ex.ToString());
+// }
+// }
+// }
+// }
+// #endregion
+
+// #region Timer read from consoles and fire event
+
+// private static void timerThreadLoop()
+// {
+// try
+// {
+// while (true)
+// {
+// readConsole();
+// Thread.Sleep(consoleReadIntervalMilliseconds);
+// }
+// }
+// catch (ThreadAbortException) { } // Expected on thread shutdown
+// }
+
+// private static void readConsole()
+// {
+// try
+// {
+
+// // Lock so we don't collide with any startup or shutdown
+// lock (Program.AppList)
+// {
+// foreach (AppExecutor app in new ArrayList(Program.AppList.Values))
+// {
+// try
+// {
+// string txt = app.GetStdOutput();
+// // Fire event with received text
+// if (!string.IsNullOrEmpty(txt))
+// Program.FireAppConsoleOutput(app.File, txt);
+// }
+// catch (Exception ex)
+// {
+// m_log.ErrorFormat("Exception reading standard output from \"{0}\": {1}", app.File, ex.ToString());
+// }
+// try
+// {
+// string txt = app.GetStdError();
+// // Fire event with received text
+// if (!string.IsNullOrEmpty(txt))
+// Program.FireAppConsoleOutput(app.File, txt);
+// }
+// catch (Exception ex)
+// {
+// m_log.ErrorFormat("Exception reading standard error from \"{0}\": {1}", app.File, ex.ToString());
+// }
+// }
+// }
+// }
+// finally
+// {
+// }
+// }
+// #endregion
+
+
+// #region Read stdOutput and stdError
+// public string GetStdOutput()
+// {
+// return GetStreamData(Output);
+// }
+// public string GetStdError()
+// {
+// return GetStreamData(Error);
+// }
+
+// private static int num = 0;
+// // Gets any data from StreamReader object, non-blocking
+// private static string GetStreamData(StreamReader sr)
+// {
+// // Can't read?
+// if (!sr.BaseStream.CanRead)
+// return "";
+
+// // Read a chunk
+// //sr.BaseStream.ReadTimeout = 100;
+// byte[] buffer = new byte[4096];
+// num++;
+// Trace.WriteLine("Start read " + num);
+// int len = sr.BaseStream.Read(buffer, 0, buffer.Length);
+// Trace.WriteLine("End read " + num + ": " + len);
+
+// // Nothing?
+// if (len <= 0)
+// return "";
+
+// // Return data
+// StringBuilder sb = new StringBuilder();
+// sb.Append(System.Text.Encoding.ASCII.GetString(buffer, 0, len));
+
+// //while (sr.Peek() >= 0)
+// //{
+// // sb.Append(Convert.ToChar(sr.Read()));
+// //}
+
+// return sb.ToString();
+// }
+// #endregion
+
+
+// }
+//}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/CommandProcessor.cs b/OpenSim/Tools/OpenSim.GridLaunch/CommandProcessor.cs
new file mode 100644
index 0000000..aca36e9
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/CommandProcessor.cs
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenSim.GridLaunch
+{
+ internal class CommandProcessor
+ {
+ public delegate void CommandLineDelegate(string application, string command, string arguments);
+ public event CommandLineDelegate CommandLine;
+
+ public bool IsCommand(string cmd)
+ {
+ if (cmd.Trim().StartsWith("/"))
+ return true;
+ return false;
+ }
+
+ public static readonly char[] cmdSplit = new char[] { ' ' };
+ public bool Process(string app, string command)
+ {
+ // Only process commands
+ if (!IsCommand(command))
+ return false;
+
+ // Remove first /
+ command = command.Trim().Remove(0, 1);
+
+ // Split cmd and args
+ string[] carg = command.Split(cmdSplit, 2);
+ if (carg.Length == 0)
+ return true;
+
+ string cmd = carg[0]; // Command
+ string arg = "";
+ if (carg.Length > 1)
+ arg = carg[1]; // Arguments
+
+ // Do we have a command?
+ if (string.IsNullOrEmpty(cmd))
+ return true;
+
+ // All is fine
+ if (CommandLine != null)
+ CommandLine(app, cmd, arg);
+ return true;
+ }
+
+ }
+}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/Console/Console.cs b/OpenSim/Tools/OpenSim.GridLaunch/GUI/Console/Console.cs
new file mode 100644
index 0000000..a04c9cf
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/GUI/Console/Console.cs
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenSim.GridLaunch.GUI.Console
+{
+ internal class Console: IGUI
+ {
+ private List Apps = new List();
+ public Console ()
+ {
+ Program.AppCreated += Program_AppCreated;
+ Program.AppRemoved += Program_AppRemoved;
+ Program.AppConsoleOutput += Program_AppConsoleOutput;
+ Program.Command.CommandLine += Command_CommandLine;
+ }
+
+ private string currentApp = "";
+ private bool quitTyped = false;
+ void Command_CommandLine(string application, string command, string arguments)
+ {
+
+ // If command is a number then someone might be trying to change console: /1, /2, etc.
+ int currentAppNum = 0;
+ if (int.TryParse(command, out currentAppNum))
+ if (currentAppNum <= Apps.Count)
+ {
+ currentApp = Apps[currentAppNum - 1];
+ System.Console.WriteLine("Changed console to app: " + currentApp);
+ } else
+ System.Console.WriteLine("Unable to change to app number: " + currentAppNum);
+
+ // Has user typed quit?
+ if (command.ToLower() == "quit")
+ quitTyped = true;
+
+ // Has user typed /list?
+ if (command.ToLower() == "list")
+ {
+ System.Console.WriteLine("/0 Log console");
+ for (int i = 1; i <= Apps.Count; i++)
+ {
+ System.Console.WriteLine(string.Format("/{0} {1}", i, Apps[i - 1]));
+ }
+ }
+ }
+ #region Module Start / Stop
+ public void StartGUI()
+ {
+ // Console start
+ System.Console.WriteLine("Console GUI");
+ System.Console.WriteLine("Use commands /0, /1, /2, etc to switch between applications.");
+ System.Console.WriteLine("Type /list for list of applications.");
+ System.Console.WriteLine("Anything that doesn't start with a / will be sent to selected application");
+ System.Console.WriteLine("type /quit to exit");
+
+
+ while (quitTyped == false)
+ {
+ string line = System.Console.ReadLine().TrimEnd("\r\n".ToCharArray());
+ Program.Write(currentApp, line);
+ }
+ // We are done
+ System.Console.WriteLine("Console exit.");
+ }
+
+ public void StopGUI()
+ {
+ // Console stop
+ }
+ #endregion
+
+ #region GridLaunch Events
+ void Program_AppCreated(string App)
+ {
+ System.Console.WriteLine("Started: " + App);
+ if (!Apps.Contains(App))
+ Apps.Add(App);
+ }
+
+ void Program_AppRemoved(string App)
+ {
+ System.Console.WriteLine("Stopped: " + App);
+ if (Apps.Contains(App))
+ Apps.Remove(App);
+ }
+
+ void Program_AppConsoleOutput(string App, string Text)
+ {
+ System.Console.Write(App + ": " + Text);
+ }
+ #endregion
+
+
+ }
+}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/IGUI.cs b/OpenSim/Tools/OpenSim.GridLaunch/GUI/IGUI.cs
new file mode 100644
index 0000000..45d8af7
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/GUI/IGUI.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenSim.GridLaunch.GUI
+{
+ public interface IGUI
+ {
+ void StartGUI();
+ void StopGUI();
+ }
+}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/Network/Client.cs b/OpenSim/Tools/OpenSim.GridLaunch/GUI/Network/Client.cs
new file mode 100644
index 0000000..19b27e4
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/GUI/Network/Client.cs
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+using System;
+using System.Collections.Generic;
+using System.Net.Sockets;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace OpenSim.GridLaunch.GUI.Network
+{
+ internal class Client
+ {
+ public TcpClient tcpClient;
+ private byte[] readBuffer = new byte[4096];
+ private byte[] writeBuffer;
+ private TCPD tcp;
+ private string inputData = "";
+ private object inputDataLock = new object();
+ public Client(TCPD _tcp, TcpClient Client)
+ {
+ tcp = _tcp;
+ tcpClient = Client;
+ asyncReadStart();
+ Write("OpenSim TCP Console GUI");
+ Write("Use commands /0, /1, /2, etc to switch between applications.");
+ Write("Type /list for list of applications.");
+ Write("Anything that doesn't start with a / will be sent to selected application");
+ Write("type /quit to exit");
+
+ }
+
+ private void asyncReadStart()
+ {
+ tcpClient.GetStream().BeginRead(readBuffer, 0, readBuffer.Length, asyncReadCallBack, null);
+ }
+
+ //private Regex LineExtractor = new Regex("^(.*)$")
+ private void asyncReadCallBack(IAsyncResult ar)
+ {
+ try
+ {
+ // Read data
+ int len = tcpClient.GetStream().EndRead(ar);
+
+ // Send it to app
+ string newData = System.Text.Encoding.ASCII.GetString(readBuffer, 0, len);
+ //lock (inputDataLock)
+ //{
+ inputData += newData;
+ if (newData.Contains("\n"))
+ SendInputLines();
+ //}
+
+ // Start it again
+ asyncReadStart();
+ }
+ catch
+ {
+ // TODO: Remove client when we get exception
+ // Temp patch: if exception we don't call asyncReadStart()
+ }
+ }
+
+ private void SendInputLines()
+ {
+ StringBuilder line = new StringBuilder();
+ foreach (char c in inputData)
+ {
+ if (c == 13)
+ continue;
+ if (c == 10)
+ {
+ Program.WriteLine(tcp.currentApp, line.ToString());
+ line = new StringBuilder();
+ continue;
+ }
+ line.Append(c);
+ }
+ // We'll keep whatever is left over
+ inputData = line.ToString();
+ }
+
+ public void Write(string Text)
+ {
+ writeBuffer = Encoding.ASCII.GetBytes(Text);
+ tcpClient.GetStream().Write(writeBuffer, 0, writeBuffer.Length);
+ }
+ }
+}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/Network/TCPD.cs b/OpenSim/Tools/OpenSim.GridLaunch/GUI/Network/TCPD.cs
new file mode 100644
index 0000000..5524e21
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/GUI/Network/TCPD.cs
@@ -0,0 +1,231 @@
+/*
+ * 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.
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Net;
+using System.Net.Sockets;
+using System.Reflection;
+using System.Text;
+using System.Threading;
+using log4net;
+
+namespace OpenSim.GridLaunch.GUI.Network
+{
+ public class TCPD : IGUI, IDisposable
+ {
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private List Clients = new List();
+
+ private readonly int defaultPort = 7998;
+ private TcpListener tcpListener;
+ private Thread listenThread;
+ private Thread clientThread;
+
+
+ private List Apps = new List();
+ internal string currentApp = "";
+ private bool quitTyped = false;
+
+ public TCPD()
+ {
+ Program.AppCreated += Program_AppCreated;
+ Program.AppRemoved += Program_AppRemoved;
+ Program.AppConsoleOutput += Program_AppConsoleOutput;
+ Program.Command.CommandLine += Command_CommandLine;
+
+ }
+
+ ~TCPD()
+ {
+ Dispose();
+ }
+ private bool isDisposed = false;
+ ///
+ ///Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ ///
+ ///2
+ public void Dispose()
+ {
+ if (isDisposed)
+ return;
+ isDisposed = true;
+ tcpd_Stop();
+ }
+
+ public void StartGUI()
+ {
+ // We are starting
+ tcpd_Start();
+ }
+
+ public void StopGUI()
+ {
+ // We are stopping
+ tcpd_Stop();
+ }
+
+
+ #region GridLaunch Events
+ private void Command_CommandLine(string application, string command, string arguments)
+ {
+ // If command is a number then someone might be trying to change console: /1, /2, etc.
+ int currentAppNum = 0;
+ if (int.TryParse(command, out currentAppNum))
+ if (currentAppNum <= Apps.Count)
+ {
+ currentApp = Apps[currentAppNum - 1];
+ TCPWriteToAll("Changed console to app: " + currentApp + Environment.NewLine);
+ }
+ else
+ TCPWriteToAll("Unable to change to app number: " + currentAppNum + Environment.NewLine);
+
+ // Has user typed quit?
+ if (command.ToLower() == "quit")
+ quitTyped = true;
+
+ // Has user typed /list?
+ if (command.ToLower() == "list")
+ {
+ TCPWriteToAll("/0 Log console");
+ for (int i = 1; i <= Apps.Count; i++)
+ {
+ TCPWriteToAll(string.Format("/{0} {1}", i, Apps[i - 1]));
+ }
+ }
+
+ }
+
+ void Program_AppCreated(string App)
+ {
+ TCPWriteToAll("Started: " + App);
+ if (!Apps.Contains(App))
+ Apps.Add(App);
+ }
+
+ void Program_AppRemoved(string App)
+ {
+ TCPWriteToAll("Stopped: " + App);
+ if (Apps.Contains(App))
+ Apps.Remove(App);
+ }
+
+ private void Program_AppConsoleOutput(string App, string Text)
+ {
+ TCPWriteToAll(App, Text);
+ }
+
+ #endregion
+
+ private void tcpd_Start()
+ {
+ listenThread = new Thread(new ThreadStart(ListenForClients));
+ listenThread.Name = "TCPDThread";
+ listenThread.IsBackground = true;
+ listenThread.Start();
+
+ while (!quitTyped)
+ {
+ Thread.Sleep(500);
+ }
+
+ //clientThread = new Thread(new ThreadStart(ProcessClients));
+ //clientThread.Name = "TCPClientThread";
+ //clientThread.IsBackground = true;
+ ////clientThread.Start();
+
+ }
+ private void tcpd_Stop()
+ {
+ StopThread(listenThread);
+ StopThread(clientThread);
+ }
+ private void ListenForClients()
+ {
+ int Port = 0;
+ int.TryParse(Program.Settings["TCPPort"], out Port);
+ if (Port < 1)
+ Port = defaultPort;
+
+ m_log.Info("Starting TCP Server on port " + Port);
+ this.tcpListener = new TcpListener(IPAddress.Any, Port);
+
+ this.tcpListener.Start();
+
+ while (true)
+ {
+ // Blocks until a client has connected to the server
+ TcpClient tcpClient = this.tcpListener.AcceptTcpClient();
+ Client client = new Client(this, tcpClient);
+
+ lock (Clients)
+ {
+ Clients.Add(client);
+ }
+ System.Threading.Thread.Sleep(500);
+ }
+ }
+
+ private static void StopThread(Thread t)
+ {
+ if (t != null)
+ {
+ m_log.Debug("Stopping thread " + t.Name);
+ try
+ {
+ if (t.IsAlive)
+ t.Abort();
+ t.Join(2000);
+ t = null;
+ }
+ catch (Exception ex)
+ {
+ m_log.Error("Exception stopping thread: " + ex.ToString());
+ }
+ }
+ }
+
+ private void TCPWriteToAll(string app, string text)
+ {
+ TCPWriteToAll(text);
+ }
+ private void TCPWriteToAll(string text)
+ {
+ foreach (Client c in new ArrayList(Clients))
+ {
+ try
+ {
+ c.Write(text);
+ } catch (Exception ex)
+ {
+ m_log.Error("Exception writing to TCP: " + ex.ToString());
+ }
+ }
+ }
+
+ }
+}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/Service/Service.cs b/OpenSim/Tools/OpenSim.GridLaunch/GUI/Service/Service.cs
new file mode 100644
index 0000000..c6fd501
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/GUI/Service/Service.cs
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+using System;
+using System.Collections.Generic;
+using System.ServiceProcess;
+using System.Text;
+using OpenSim.GridLaunch.GUI;
+
+namespace OpenSim.GridLaunch
+{
+ internal class Service: ServiceBase, IGUI
+ {
+ private ServiceBase[] ServicesToRun;
+ public Service()
+ {
+ ServicesToRun = new ServiceBase[] {this};
+ }
+
+ public void StartGUI()
+ {
+ ServiceBase.Run(ServicesToRun);
+ }
+
+ public void StopGUI()
+ {
+ // Nothing
+ }
+
+ protected override void OnStart(string[] args)
+ {
+ // Command line arguments override settings
+ Program.Settings.ParseCommandArguments(args);
+ }
+
+ protected override void OnStop()
+ {
+ Program.Shutdown();
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/OpenSim Bottom Border.png b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/OpenSim Bottom Border.png
new file mode 100644
index 0000000..b3594b6
Binary files /dev/null and b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/OpenSim Bottom Border.png differ
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/OpenSim Right Border.png b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/OpenSim Right Border.png
new file mode 100644
index 0000000..8b03281
Binary files /dev/null and b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/OpenSim Right Border.png differ
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/OpenSim.png b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/OpenSim.png
new file mode 100644
index 0000000..257ca39
Binary files /dev/null and b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/OpenSim.png differ
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ProcessPanel.Designer.cs b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ProcessPanel.Designer.cs
new file mode 100644
index 0000000..1498791
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ProcessPanel.Designer.cs
@@ -0,0 +1,224 @@
+namespace OpenSim.GridLaunch.GUI.WinForm
+{
+ partial class ProcessPanel
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ProcessPanel));
+ this.tabControl1 = new System.Windows.Forms.TabControl();
+ this.tabLogs = new System.Windows.Forms.TabPage();
+ this.btnShutdown = new System.Windows.Forms.Button();
+ this.pictureBox2 = new System.Windows.Forms.PictureBox();
+ this.pictureBox1 = new System.Windows.Forms.PictureBox();
+ this.pictureBox3 = new System.Windows.Forms.PictureBox();
+ this.tabSettings = new System.Windows.Forms.TabPage();
+ this.cblStartupComponents = new System.Windows.Forms.CheckedListBox();
+ this.gbStartupComponents = new System.Windows.Forms.GroupBox();
+ this.btnSave = new System.Windows.Forms.Button();
+ this.ucLogWindow1 = new OpenSim.GridLaunch.GUI.WinForm.ucLogWindow();
+ this.label1 = new System.Windows.Forms.Label();
+ this.tabControl1.SuspendLayout();
+ this.tabLogs.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).BeginInit();
+ this.tabSettings.SuspendLayout();
+ this.gbStartupComponents.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // tabControl1
+ //
+ this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.tabControl1.Controls.Add(this.tabSettings);
+ this.tabControl1.Controls.Add(this.tabLogs);
+ this.tabControl1.Location = new System.Drawing.Point(-1, 123);
+ this.tabControl1.Name = "tabControl1";
+ this.tabControl1.SelectedIndex = 0;
+ this.tabControl1.Size = new System.Drawing.Size(632, 275);
+ this.tabControl1.TabIndex = 0;
+ //
+ // tabLogs
+ //
+ this.tabLogs.Controls.Add(this.ucLogWindow1);
+ this.tabLogs.Location = new System.Drawing.Point(4, 22);
+ this.tabLogs.Name = "tabLogs";
+ this.tabLogs.Padding = new System.Windows.Forms.Padding(3);
+ this.tabLogs.Size = new System.Drawing.Size(624, 249);
+ this.tabLogs.TabIndex = 0;
+ this.tabLogs.Text = "Logs";
+ this.tabLogs.UseVisualStyleBackColor = true;
+ //
+ // btnShutdown
+ //
+ this.btnShutdown.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnShutdown.Location = new System.Drawing.Point(542, 400);
+ this.btnShutdown.Name = "btnShutdown";
+ this.btnShutdown.Size = new System.Drawing.Size(75, 23);
+ this.btnShutdown.TabIndex = 1;
+ this.btnShutdown.Text = "Shutdown";
+ this.btnShutdown.UseVisualStyleBackColor = true;
+ this.btnShutdown.Click += new System.EventHandler(this.btnShutdown_Click);
+ //
+ // pictureBox2
+ //
+ this.pictureBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.pictureBox2.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox2.Image")));
+ this.pictureBox2.Location = new System.Drawing.Point(585, -1);
+ this.pictureBox2.Name = "pictureBox2";
+ this.pictureBox2.Size = new System.Drawing.Size(46, 124);
+ this.pictureBox2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
+ this.pictureBox2.TabIndex = 3;
+ this.pictureBox2.TabStop = false;
+ //
+ // pictureBox1
+ //
+ this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));
+ this.pictureBox1.Location = new System.Drawing.Point(-1, -1);
+ this.pictureBox1.Name = "pictureBox1";
+ this.pictureBox1.Size = new System.Drawing.Size(586, 124);
+ this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
+ this.pictureBox1.TabIndex = 2;
+ this.pictureBox1.TabStop = false;
+ //
+ // pictureBox3
+ //
+ this.pictureBox3.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.pictureBox3.Image = global::OpenSim.GridLaunch.Properties.Resources.OpenSim_Bottom_Border;
+ this.pictureBox3.Location = new System.Drawing.Point(-1, 120);
+ this.pictureBox3.Name = "pictureBox3";
+ this.pictureBox3.Size = new System.Drawing.Size(632, 310);
+ this.pictureBox3.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
+ this.pictureBox3.TabIndex = 4;
+ this.pictureBox3.TabStop = false;
+ //
+ // tabSettings
+ //
+ this.tabSettings.Controls.Add(this.label1);
+ this.tabSettings.Controls.Add(this.btnSave);
+ this.tabSettings.Controls.Add(this.gbStartupComponents);
+ this.tabSettings.Location = new System.Drawing.Point(4, 22);
+ this.tabSettings.Name = "tabSettings";
+ this.tabSettings.Padding = new System.Windows.Forms.Padding(3);
+ this.tabSettings.Size = new System.Drawing.Size(624, 249);
+ this.tabSettings.TabIndex = 1;
+ this.tabSettings.Text = "Settings";
+ this.tabSettings.UseVisualStyleBackColor = true;
+ //
+ // cblStartupComponents
+ //
+ this.cblStartupComponents.CheckOnClick = true;
+ this.cblStartupComponents.FormattingEnabled = true;
+ this.cblStartupComponents.Location = new System.Drawing.Point(6, 19);
+ this.cblStartupComponents.Name = "cblStartupComponents";
+ this.cblStartupComponents.Size = new System.Drawing.Size(202, 109);
+ this.cblStartupComponents.TabIndex = 0;
+ //
+ // gbStartupComponents
+ //
+ this.gbStartupComponents.Controls.Add(this.cblStartupComponents);
+ this.gbStartupComponents.Location = new System.Drawing.Point(9, 6);
+ this.gbStartupComponents.Name = "gbStartupComponents";
+ this.gbStartupComponents.Size = new System.Drawing.Size(214, 136);
+ this.gbStartupComponents.TabIndex = 1;
+ this.gbStartupComponents.TabStop = false;
+ this.gbStartupComponents.Text = "Startup components";
+ //
+ // btnSave
+ //
+ this.btnSave.Location = new System.Drawing.Point(9, 148);
+ this.btnSave.Name = "btnSave";
+ this.btnSave.Size = new System.Drawing.Size(92, 23);
+ this.btnSave.TabIndex = 2;
+ this.btnSave.Text = "Save settings";
+ this.btnSave.UseVisualStyleBackColor = true;
+ this.btnSave.Click += new System.EventHandler(this.btnSave_Click);
+ //
+ // ucLogWindow1
+ //
+ this.ucLogWindow1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.ucLogWindow1.Location = new System.Drawing.Point(3, 3);
+ this.ucLogWindow1.Name = "ucLogWindow1";
+ this.ucLogWindow1.Size = new System.Drawing.Size(618, 243);
+ this.ucLogWindow1.TabIndex = 0;
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(108, 149);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(259, 13);
+ this.label1.TabIndex = 3;
+ this.label1.Text = "* You have to restart app before changes take effect.";
+ //
+ // ProcessPanel
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(629, 428);
+ this.Controls.Add(this.pictureBox2);
+ this.Controls.Add(this.pictureBox1);
+ this.Controls.Add(this.btnShutdown);
+ this.Controls.Add(this.tabControl1);
+ this.Controls.Add(this.pictureBox3);
+ this.Name = "ProcessPanel";
+ this.Text = "OpenSim GUI alpha";
+ this.Load += new System.EventHandler(this.ProcessPanel_Load);
+ this.tabControl1.ResumeLayout(false);
+ this.tabLogs.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).EndInit();
+ this.tabSettings.ResumeLayout(false);
+ this.tabSettings.PerformLayout();
+ this.gbStartupComponents.ResumeLayout(false);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TabControl tabControl1;
+ private System.Windows.Forms.TabPage tabLogs;
+ private System.Windows.Forms.Button btnShutdown;
+ private ucLogWindow ucLogWindow1;
+ private System.Windows.Forms.PictureBox pictureBox1;
+ private System.Windows.Forms.PictureBox pictureBox2;
+ private System.Windows.Forms.PictureBox pictureBox3;
+ private System.Windows.Forms.TabPage tabSettings;
+ private System.Windows.Forms.GroupBox gbStartupComponents;
+ private System.Windows.Forms.CheckedListBox cblStartupComponents;
+ private System.Windows.Forms.Button btnSave;
+ private System.Windows.Forms.Label label1;
+
+ }
+}
\ No newline at end of file
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ProcessPanel.cs b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ProcessPanel.cs
new file mode 100644
index 0000000..dbf97d6
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ProcessPanel.cs
@@ -0,0 +1,288 @@
+/*
+ * 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.
+ */
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+
+namespace OpenSim.GridLaunch.GUI.WinForm
+{
+ public partial class ProcessPanel : Form, IGUI
+ {
+ public ProcessPanel()
+ {
+ Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+
+ InitializeComponent();
+ Program.AppCreated += Program_AppCreated;
+ Program.AppRemoved += Program_AppRemoved;
+ Program.AppConsoleOutput += Program_AppConsoleOutput;
+ Program.AppConsoleError += Program_AppConsoleError;
+ log4netAppender.LogLine += log4netAppender_LogLine;
+ }
+
+ #region Module Start / Stop
+ public void StartGUI()
+ {
+ Application.Run(this);
+ }
+
+ public void StopGUI()
+ {
+ this.Close();
+ }
+ #endregion
+
+ #region Main log tab
+ void log4netAppender_LogLine(Color color, string LogText)
+ {
+ ucLogWindow1.Write(color, LogText);
+ }
+ #endregion
+
+ #region Form events
+ private void btnShutdown_Click(object sender, EventArgs e)
+ {
+ Program.Shutdown();
+ }
+ #endregion
+
+ #region GridLaunch Events
+ public delegate void Program_AppCreatedDelegate(string App);
+ public void Program_AppCreated(string App)
+ {
+ if (this.InvokeRequired) {
+ this.Invoke(new Program_AppCreatedDelegate(Program_AppCreated), App);
+ return;
+ }
+
+ Trace.WriteLine("Start: " + App);
+
+ // Do we already have app window for that app?
+ if (AppWindow_Get(App) != null)
+ return;
+
+ // New log window
+ ucAppWindow aw = new ucAppWindow();
+ // New tab page
+ TabPage tp = new TabPage(App);
+ // Add log window into tab page
+ tp.Controls.Add(aw);
+ // Add tab page into tab control
+ tabControl1.TabPages.Add(tp);
+ // Add it all to our internal list
+ AppWindow_Add(App, aw);
+ // Hook up events
+ aw.LineEntered += AppWindow_LineEntered;
+
+ // Fill log window fully inside tab page
+ aw.Dock = DockStyle.Fill;
+ }
+
+
+ public delegate void Program_AppRemovedDelegate(string App);
+ public void Program_AppRemoved(string App)
+ {
+ if (this.InvokeRequired) {
+ this.Invoke(new Program_AppRemovedDelegate(Program_AppRemoved), App);
+ return;
+ }
+
+ Trace.WriteLine("Stop: " + App);
+
+ // Get app window
+ ucAppWindow aw = AppWindow_Get(App);
+ if (aw == null)
+ return;
+
+ // Get its tab page
+ TabPage tp = aw.Parent as TabPage;
+
+ if (tp != null)
+ {
+ // Remove tab page from tab control
+ tabControl1.TabPages.Remove(tp);
+ // Remove app window from tab
+ tp.Controls.Remove(aw);
+ }
+
+ // Dispose of app window
+ aw.Dispose();
+
+ // Dispose of tab page
+ if (tp != null)
+ tp.Dispose();
+
+ // Remove from our internal list
+ AppWindow_Remove(App);
+ }
+
+
+ public delegate void Program_AppConsoleOutputDelegate(string App, string LogText);
+ void Program_AppConsoleOutput(string App, string LogText)
+ {
+ if (this.InvokeRequired)
+ {
+ this.Invoke(new Program_AppConsoleOutputDelegate(Program_AppConsoleOutput), App, LogText);
+ return;
+ }
+
+ // Get app window
+ ucAppWindow aw = AppWindow_Get(App);
+ // Write text to it
+ if (aw != null)
+ aw.Write(System.Drawing.Color.Black, LogText);
+ }
+
+ public delegate void Program_AppConsoleErrorDelegate(string App, string LogText);
+ void Program_AppConsoleError(string App, string LogText)
+ {
+ if (this.InvokeRequired) {
+ this.Invoke(new Program_AppConsoleErrorDelegate(Program_AppConsoleError), App, LogText);
+ return;
+ }
+
+ // Get app window
+ ucAppWindow aw = AppWindow_Get(App);
+ // Write text to it
+ if (aw != null)
+ aw.Write(System.Drawing.Color.Red, LogText);
+
+ }
+ #endregion
+
+ #region App Window events
+ private void AppWindow_LineEntered(ucAppWindow AppWindow, string LogText)
+ {
+ Program.WriteLine(AppWindow_Get(AppWindow), LogText);
+ }
+ #endregion
+
+ private void ProcessPanel_Load(object sender, EventArgs e)
+ {
+ string[] arr = new string[Program.Settings.Components.Keys.Count];
+ Program.Settings.Components.Keys.CopyTo(arr, 0);
+ cblStartupComponents.Items.AddRange(arr);
+
+ // Now correct all check states
+ for (int i = 0; i < cblStartupComponents.Items.Count; i++ )
+ {
+ string _name = cblStartupComponents.Items[i] as string;
+ bool _checked = Program.Settings.Components[_name];
+
+ cblStartupComponents.SetItemChecked(i, _checked);
+ }
+
+
+ }
+
+
+
+
+ #region Internal App Window list and functions
+ private Dictionary _appWindows = new Dictionary();
+ private Dictionary _appWindows_rev = new Dictionary();
+ private void AppWindow_Add(string AppWindowName, ucAppWindow AppWindow)
+ {
+ lock (_appWindows)
+ {
+ _appWindows.Add(AppWindowName, AppWindow);
+ _appWindows_rev.Add(AppWindow, AppWindowName);
+ // Hook events
+ AppWindow.LineEntered += AppWindow_LineEntered;
+ }
+ }
+ private void AppWindow_Remove(ucAppWindow AppWindow)
+ {
+ lock (_appWindows)
+ {
+ if (_appWindows_rev.ContainsKey(AppWindow))
+ {
+ // Unhook events
+ AppWindow.LineEntered -= AppWindow_LineEntered;
+ // Delete from list
+ string name = _appWindows_rev[AppWindow];
+ _appWindows.Remove(name);
+ _appWindows_rev.Remove(AppWindow);
+ }
+ }
+ }
+ private void AppWindow_Remove(string AppWindowName)
+ {
+ lock (_appWindows)
+ {
+ if (_appWindows.ContainsKey(AppWindowName))
+ {
+ ucAppWindow AppWindow = _appWindows[AppWindowName];
+ // Unhook events
+ AppWindow.LineEntered -= AppWindow_LineEntered;
+ // Delete from list
+ _appWindows.Remove(AppWindowName);
+ _appWindows_rev.Remove(AppWindow);
+ }
+ }
+ }
+ private string AppWindow_Get(ucAppWindow AppWindow)
+ {
+ lock (_appWindows)
+ {
+ if (_appWindows_rev.ContainsKey(AppWindow))
+ return _appWindows_rev[AppWindow];
+ }
+ return null;
+ }
+ private ucAppWindow AppWindow_Get(string AppWindowName)
+ {
+ lock (_appWindows)
+ {
+ if (_appWindows.ContainsKey(AppWindowName))
+ return _appWindows[AppWindowName];
+ }
+ return null;
+ }
+ #endregion
+
+ private void btnSave_Click(object sender, EventArgs e)
+ {
+ Program.Settings.Components.Clear();
+ for (int i = 0; i < cblStartupComponents.Items.Count; i++)
+ {
+ string _name = cblStartupComponents.Items[i] as string;
+ bool _checked = cblStartupComponents.GetItemChecked(i);
+
+ Program.Settings.Components.Add(_name, _checked);
+ Program.Settings.SaveConfig();
+ }
+ }
+
+ }
+}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ProcessPanel.resx b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ProcessPanel.resx
new file mode 100644
index 0000000..361d658
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ProcessPanel.resx
@@ -0,0 +1,882 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAAAEAAAB8CAIAAAAny03BAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAOpgAA
+ DqYBh9ypbwAAAYpJREFUKFOV0fkrH3AYwPG3Y84NW2xzj76btomJHE20NUcpi9DKUlt+0i6EjbnmiOWY
+ ZTKSo69YtolNRHOEYWsIK8sksiZZU5Ompo8n379gP7x63s/z+fEDdz7w3+4Oondv6JD+/WH0H4xgkDx6
+ yDBlDMPUcY6kfcQofQKjjEmMH05h8ugTppmfMc36gtnjacyzZziaM8uxvDks8uexfLKAVcFXjhctcqL4
+ G9YlS9iUfufk02VOla9wumIV28o17KvWcXj+A8fqnzi92MC5ZhOX2i1cX/5CU/8bTcM25xr/4Na0w/mW
+ XS5q/+LeuodH2z882ve51KHweq3wfqvw6VT4din83ykC3isu9yoC+xRB/Qq7bHDIBfs8sJPpWABOxXIr
+ lFsRuJaJCtA8gzPibDVcqAE34VknXStv0n7N0rJ7N0m3QIAWrrZBYCtcewVXRLAIeQMRnXKTGdmtE9YF
+ 0T0QLh0lM6YProu4fgjthRsDcFO+79YQJIhY6fhBSByB26M6SeM6idIJwxwAjlSW4/2by3sAAAAASUVO
+ RK5CYII=
+
+
+
+
+ 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
+ OxA5OCbeDtx9K3DPLXK640Zg0m2SxhFsyEF63x2SBmfMDVIQl9RsuASBrCx4dt0MSL4dkHgrYNdNUvWO
+ m/6xN/ygz64bvjtv+MTf9Iq76Rl/02PnDbfNV12h/7orTpuuOq5ttlt/2WZlk/W6ZstVTebRTcoVjWZR
+ jfLIepNFdUaL66QLayXL6g1mVIvn1ujPrhYtqhVNuSicfUk48YLOrIuC6RcF484LJp7nj0WIRkELIAeE
+ mH2JNwYB03nejIskjfwhQBp6aTgFnvHnyKXJNAFO8IymObiE04kI+3BHjeYgDTkzL6lEAR0hB/lgQ3Gk
+ cUQaVSCBq+ojCk6hmUwZJFgaRQi40iMYUAvTQa0Ypz9nfwwVbvxw8/df6n9482qAbcLZNboTLogmXxLN
+ rtZfWi+edslgYZ1kUZ00ssF4Wo0JQC6q0XRFo2J1szK62WLLVQpyV222XrXbcMVh61XHbdec1lx22XXD
+ Jfa6647rbvE33Xfc8Nh23XPnTc/Y616brgFRvHfd9N59E+jik3jbZ8cNH6S3XScUd9Nn1w2fPTd9Ym+Q
+ NEVHkgaBB8e9t0gOOHfd9Nl+nZxGX1FdAlyxq6At1wgPchJueW+5huq8dt7wggJrrwJ0AWbu26+7xV53
+ 236d6em8/Zrj9msO6y/bbbpiu/GKTWSj1eYrlmuaCbCtazZb0QhQl6H5C2ql06oNF9dJFtSJ59WKF9Tq
+ LakjSwEYbfx54bjzOjMuCaZcEMy8JJhwgT/1IsGVaQAebDCep6hDAQn5I8/yJlEIwWk/7EDSSwyuplwk
+ NBx3wiiezakmzMgBD44RuE+GSAvxH6I3ygkGAnKXyBH8uARCceQjAQWQABvk44iyuIR8Vgu7ikykUQur
+ CEIIWNJMcKIWKM/pz9mfGz/c/P1X+x/e/DodeOq5NcL5tboL60RL6vUW1ukvqhMvbTCYVC1ZUi9d3mC0
+ pM5kaYNsSb18Xj0CGsXGK8o1zRZrL1tGN1mtabbZeNVm4xWAhN3mq/ZAuw1XHLdfd9py1WkHQRGXXTdd
+ tl1z2XnDJeY6AT+EehuvusbddN12jdDWa67br7nuvEmOSG++5hpzzXXXTYSDrltoGoRM5IAZxVEWzLgK
+ fpazm57uuOG6E3STnMai3hukxlVXSNUx1503XyH6rL/iGHXZYdMV+5jrdhuv2G64YgPl0YR1pCHmQO6o
+ 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
+
+
+
\ No newline at end of file
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucAppWindow.Designer.cs b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucAppWindow.Designer.cs
new file mode 100644
index 0000000..1ff7d43
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucAppWindow.Designer.cs
@@ -0,0 +1,72 @@
+namespace OpenSim.GridLaunch.GUI.WinForm
+{
+ partial class ucAppWindow
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.ucLogWindow1 = new OpenSim.GridLaunch.GUI.WinForm.ucLogWindow();
+ this.ucInputField1 = new OpenSim.GridLaunch.GUI.WinForm.ucInputField();
+ this.SuspendLayout();
+ //
+ // ucLogWindow1
+ //
+ this.ucLogWindow1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.ucLogWindow1.Location = new System.Drawing.Point(3, 3);
+ this.ucLogWindow1.Name = "ucLogWindow1";
+ this.ucLogWindow1.Size = new System.Drawing.Size(232, 132);
+ this.ucLogWindow1.TabIndex = 0;
+ //
+ // ucInputField1
+ //
+ this.ucInputField1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.ucInputField1.Location = new System.Drawing.Point(0, 141);
+ this.ucInputField1.Name = "ucInputField1";
+ this.ucInputField1.Size = new System.Drawing.Size(234, 30);
+ this.ucInputField1.TabIndex = 1;
+ //
+ // ucAppWindow
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.ucInputField1);
+ this.Controls.Add(this.ucLogWindow1);
+ this.DoubleBuffered = true;
+ this.Name = "ucAppWindow";
+ this.Size = new System.Drawing.Size(235, 166);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private ucLogWindow ucLogWindow1;
+ private ucInputField ucInputField1;
+ }
+}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucAppWindow.cs b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucAppWindow.cs
new file mode 100644
index 0000000..66072dc
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucAppWindow.cs
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Text;
+using System.Windows.Forms;
+
+namespace OpenSim.GridLaunch.GUI.WinForm
+{
+ public partial class ucAppWindow : UserControl
+ {
+ // Just forwarding from ucInputField1
+ public delegate void LineEnteredDelegate(ucAppWindow AppWindow, string Text);
+ public event LineEnteredDelegate LineEntered;
+
+ public ucAppWindow()
+ {
+ InitializeComponent();
+ ucInputField1.LineEntered += ucInputField1_LineEntered;
+ }
+
+ #region Forward Text Input Event and Log Write Function
+ void ucInputField1_LineEntered(string Text)
+ {
+ if (LineEntered != null)
+ LineEntered(this, Text);
+ }
+
+ public void Write(Color color, string LogText)
+ {
+ ucLogWindow1.Write(color, LogText);
+ }
+ #endregion
+
+ }
+}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucAppWindow.resx b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucAppWindow.resx
new file mode 100644
index 0000000..19dc0dd
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucAppWindow.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucInputField.Designer.cs b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucInputField.Designer.cs
new file mode 100644
index 0000000..1eaec69
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucInputField.Designer.cs
@@ -0,0 +1,77 @@
+namespace OpenSim.GridLaunch.GUI.WinForm
+{
+ partial class ucInputField
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.txtInput = new System.Windows.Forms.TextBox();
+ this.btnSend = new System.Windows.Forms.Button();
+ this.SuspendLayout();
+ //
+ // txtInput
+ //
+ this.txtInput.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.txtInput.Location = new System.Drawing.Point(3, 2);
+ this.txtInput.Name = "txtInput";
+ this.txtInput.Size = new System.Drawing.Size(289, 20);
+ this.txtInput.TabIndex = 0;
+ this.txtInput.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.txtInput_KeyPress);
+ //
+ // btnSend
+ //
+ this.btnSend.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnSend.Location = new System.Drawing.Point(295, 0);
+ this.btnSend.Name = "btnSend";
+ this.btnSend.Size = new System.Drawing.Size(75, 23);
+ this.btnSend.TabIndex = 3;
+ this.btnSend.Text = "&Send";
+ this.btnSend.UseVisualStyleBackColor = true;
+ this.btnSend.Click += new System.EventHandler(this.btnSend_Click);
+ //
+ // ucInputField
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.btnSend);
+ this.Controls.Add(this.txtInput);
+ this.Name = "ucInputField";
+ this.Size = new System.Drawing.Size(373, 25);
+ this.Load += new System.EventHandler(this.ucInputField_Load);
+ this.Resize += new System.EventHandler(this.ucInputField_Resize);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TextBox txtInput;
+ private System.Windows.Forms.Button btnSend;
+ }
+}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucInputField.cs b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucInputField.cs
new file mode 100644
index 0000000..5ffa275
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucInputField.cs
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Drawing;
+using System.Data;
+using System.Text;
+using System.Windows.Forms;
+
+namespace OpenSim.GridLaunch.GUI.WinForm
+{
+ public partial class ucInputField : UserControl
+ {
+ public delegate void LineEnteredDelegate(string Text);
+ public event LineEnteredDelegate LineEntered;
+
+ public List History = new List();
+
+ public ucInputField()
+ {
+ InitializeComponent();
+ }
+
+ private void ucInputField_Load(object sender, EventArgs e)
+ {
+ _resize();
+ }
+
+ private void ucInputField_Resize(object sender, EventArgs e)
+ {
+ _resize();
+ }
+
+ private void _resize()
+ {
+ Height = txtInput.Height + 10;
+ }
+
+ private void btnSend_Click(object sender, EventArgs e)
+ {
+ Send();
+ }
+
+ private void txtInput_KeyPress(object sender, KeyPressEventArgs e)
+ {
+ //Trace.WriteLine("KeyChar: " + ((int)e.KeyChar).ToString());
+ if (e.KeyChar == 13)
+ {
+ e.Handled = true;
+ Send();
+ }
+
+ // TODO: Add arrow up/down history functions
+ }
+
+ private void Send()
+ {
+ // Remove \r\n at end
+ string txt = txtInput.Text.TrimEnd("\r\n".ToCharArray());
+
+ // Fire event
+ if (LineEntered != null)
+ LineEntered(txt);
+
+ // Add to history
+ History.Add(txtInput.Text);
+
+ txtInput.Text = "";
+ }
+ }
+}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucInputField.resx b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucInputField.resx
new file mode 100644
index 0000000..19dc0dd
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucInputField.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucLogWindow.Designer.cs b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucLogWindow.Designer.cs
new file mode 100644
index 0000000..839fe99
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucLogWindow.Designer.cs
@@ -0,0 +1,62 @@
+namespace OpenSim.GridLaunch.GUI.WinForm
+{
+ partial class ucLogWindow
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.txtLog = new System.Windows.Forms.TextBox();
+ this.SuspendLayout();
+ //
+ // txtLog
+ //
+ this.txtLog.BackColor = System.Drawing.SystemColors.Window;
+ this.txtLog.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.txtLog.Location = new System.Drawing.Point(0, 0);
+ this.txtLog.Multiline = true;
+ this.txtLog.Name = "txtLog";
+ this.txtLog.ReadOnly = true;
+ this.txtLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+ this.txtLog.Size = new System.Drawing.Size(150, 150);
+ this.txtLog.TabIndex = 0;
+ this.txtLog.TextChanged += new System.EventHandler(this.txtLog_TextChanged);
+ //
+ // ucLogWindow
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.txtLog);
+ this.Name = "ucLogWindow";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TextBox txtLog;
+ }
+}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucLogWindow.cs b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucLogWindow.cs
new file mode 100644
index 0000000..7b35c15
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucLogWindow.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Text;
+using System.Windows.Forms;
+
+namespace OpenSim.GridLaunch.GUI.WinForm
+{
+ public partial class ucLogWindow : UserControl
+ {
+ // If text in window is more than this
+ private static readonly int logWindowMaxTextLength = 20000;
+ // Remove this much from start of it
+ private static int logWindowTrunlTextLength = 10000;
+
+ public ucLogWindow()
+ {
+ if (logWindowMaxTextLength < logWindowTrunlTextLength)
+ logWindowTrunlTextLength = logWindowMaxTextLength / 2;
+
+ InitializeComponent();
+ }
+
+ public delegate void textWriteDelegate(Color color, string LogText);
+ public void Write(Color color, string LogText)
+ {
+ // Check if we to pass task on to GUI thread
+ if (this.InvokeRequired)
+ {
+ this.Invoke(new textWriteDelegate(Write), color, LogText);
+ return;
+ }
+ // Append to window
+ try
+ {
+ if (!txtLog.IsDisposed)
+ txtLog.AppendText(LogText);
+ } catch { }
+ }
+
+ private void txtLog_TextChanged(object sender, EventArgs e)
+ {
+ // Go to bottom of window
+ txtLog.ScrollToCaret();
+
+ // Make sure amount of text in window doesn't grow too big
+ if (txtLog.Text.Length > logWindowMaxTextLength)
+ txtLog.Text = txtLog.Text.Remove(0, logWindowTrunlTextLength);
+ }
+
+ }
+}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucLogWindow.resx b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucLogWindow.resx
new file mode 100644
index 0000000..19dc0dd
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/GUI/WinForm/ucLogWindow.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/OpenSim.GridLaunch.csproj b/OpenSim/Tools/OpenSim.GridLaunch/OpenSim.GridLaunch.csproj
new file mode 100644
index 0000000..b262dd1
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/OpenSim.GridLaunch.csproj
@@ -0,0 +1,126 @@
+
+
+
+ Debug
+ AnyCPU
+ 9.0.30729
+ 2.0
+ {595D67F3-B413-4A43-8568-5B5930E3B31D}
+ Exe
+ Properties
+ OpenSim.GridLaunch
+ OpenSim.GridLaunch
+ v2.0
+ 512
+
+
+ true
+ full
+ false
+ ..\..\..\bin\
+ DEBUG;TRACE
+ prompt
+ 4
+ x86
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Component
+
+
+ Form
+
+
+ ProcessPanel.cs
+
+
+ UserControl
+
+
+ ucAppWindow.cs
+
+
+ UserControl
+
+
+ ucInputField.cs
+
+
+ UserControl
+
+
+ ucLogWindow.cs
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+
+ ProcessPanel.cs
+
+
+ ucAppWindow.cs
+
+
+ ucInputField.cs
+
+
+ ucLogWindow.cs
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+
\ No newline at end of file
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/OpenSim.GridLaunch.ini b/OpenSim/Tools/OpenSim.GridLaunch/OpenSim.GridLaunch.ini
new file mode 100644
index 0000000..c065898
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/OpenSim.GridLaunch.ini
@@ -0,0 +1,3 @@
+GUI=WinForm
+;GUI=TCPD
+;Components=c:\temp\test.bat;true
\ No newline at end of file
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/OpenSim.GridLaunch.sln b/OpenSim/Tools/OpenSim.GridLaunch/OpenSim.GridLaunch.sln
new file mode 100644
index 0000000..8f745e1
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/OpenSim.GridLaunch.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSim.GridLaunch", "OpenSim.GridLaunch.csproj", "{595D67F3-B413-4A43-8568-5B5930E3B31D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {595D67F3-B413-4A43-8568-5B5930E3B31D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {595D67F3-B413-4A43-8568-5B5930E3B31D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {595D67F3-B413-4A43-8568-5B5930E3B31D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {595D67F3-B413-4A43-8568-5B5930E3B31D}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/Program.cs b/OpenSim/Tools/OpenSim.GridLaunch/Program.cs
new file mode 100644
index 0000000..5a0bb0c
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/Program.cs
@@ -0,0 +1,245 @@
+/*
+ * 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.
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Threading;
+using log4net;
+using log4net.Appender;
+using log4net.Repository.Hierarchy;
+using OpenSim.GridLaunch.GUI;
+using OpenSim.GridLaunch.GUI.Network;
+
+namespace OpenSim.GridLaunch
+{
+ class Program
+ {
+ public static readonly string ConfigFile = "OpenSim.GridLaunch.ini";
+ internal static Dictionary AppList = new Dictionary();
+ private static readonly int delayBetweenExecuteSeconds = 10;
+ //private static readonly int consoleReadIntervalMilliseconds = 50;
+ ////private static readonly Timer readTimer = new Timer(readConsole, null, Timeout.Infinite, Timeout.Infinite);
+ //private static Thread timerThread;
+ //private static object timerThreadLock = new object();
+ private static IGUI GUIModule;
+ private static string GUIModuleName = "";
+ public static readonly CommandProcessor Command = new CommandProcessor();
+ public static readonly Settings Settings = new Settings();
+
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ public delegate void AppConsoleOutputDelegate(string App, string Text);
+ public static event AppConsoleOutputDelegate AppConsoleOutput;
+ public delegate void AppConsoleErrorDelegate(string App, string Text);
+ public static event AppConsoleErrorDelegate AppConsoleError;
+ public delegate void AppCreatedDelegate(string App);
+ public static event AppCreatedDelegate AppCreated;
+ public delegate void AppRemovedDelegate(string App);
+ public static event AppRemovedDelegate AppRemoved;
+
+ internal static void FireAppConsoleOutput(string App, string Text)
+ {
+ if (AppConsoleOutput != null)
+ AppConsoleOutput(App, Text);
+ }
+ internal static void FireAppConsoleError(string App, string Text)
+ {
+ if (AppConsoleError != null)
+ AppConsoleError(App, Text);
+ }
+
+
+ private static readonly object startStopLock = new object();
+
+ public static string Name { get { return "OpenSim Grid executor"; } }
+
+ #region Start/Shutdown
+ static void Main(string[] args)
+ {
+ log4net.Config.XmlConfigurator.Configure();
+
+ // Startup
+ m_log.Info(Name);
+ m_log.Info(new string('-', Name.Length));
+
+ // Read settings
+ Settings.LoadConfig(ConfigFile);
+ // Command line arguments override settings
+ Settings.ParseCommandArguments(args);
+
+ // Start GUI module
+ StartGUIModule();
+
+ // Start the processes
+ ThreadPool.QueueUserWorkItem(startProcesses);
+
+ // Hand over thread control to whatever GUI module
+ GUIModule.StartGUI();
+
+ // GUI module returned, we are done
+ Shutdown();
+
+ }
+
+ private static void StartGUIModule()
+ {
+ // Create GUI module
+ GUIModuleName = Settings["GUI"];
+
+ switch (GUIModuleName.ToLower())
+ {
+ case "winform":
+ GUIModuleName = "WinForm";
+ GUIModule = new GUI.WinForm.ProcessPanel();
+ break;
+ case "service":
+ GUIModuleName = "Service";
+ GUIModule = new Service();
+ break;
+ case "tcpd":
+ GUIModuleName = "TCPD";
+ GUIModule = new TCPD();
+ break;
+ case "console":
+ default:
+ GUIModuleName = "Console";
+ GUIModule = new GUI.Console.Console();
+ break;
+ }
+ m_log.Info("GUI type: " + GUIModuleName);
+
+ }
+
+ internal static void Shutdown()
+ {
+ // Stop the processes
+ stopProcesses();
+
+ lock (startStopLock)
+ {
+ // Stop GUI module
+ if (GUIModule != null)
+ {
+ GUIModule.StopGUI();
+ GUIModule = null;
+ }
+ }
+ }
+
+ internal static void SafeDisposeOf(object obj)
+ {
+ IDisposable o = obj as IDisposable;
+ try
+ {
+ if (o != null)
+ o.Dispose();
+ }
+ catch { }
+ }
+ #endregion
+
+ #region Start / Stop applications
+ private static void startProcesses(Object stateInfo)
+ {
+ // Stop before starting
+ stopProcesses();
+
+ // Start console read timer
+ //timer_Start();
+
+ // Start the applications
+ foreach (string file in new ArrayList(Settings.Components.Keys))
+ {
+ // Is this file marked for startup?
+ if (Settings.Components[file])
+ {
+ AppExecutor app = new AppExecutor(file);
+ app.Start();
+ AppList.Add(file, app);
+ if (AppCreated != null)
+ AppCreated(app.File);
+ System.Threading.Thread.Sleep(1000*delayBetweenExecuteSeconds);
+ }
+ }
+ }
+
+ private static void stopProcesses()
+ {
+ // Stop timer
+ //timer_Stop();
+
+ // Lock so we don't collide with any timer still executing on AppList
+ lock (AppList)
+ {
+ // Start the applications
+ foreach (AppExecutor app in AppList.Values)
+ {
+ try
+ {
+ m_log.Info("Stopping: " + app.File);
+ app.Stop();
+ }
+ catch (Exception ex)
+ {
+ m_log.ErrorFormat("Exception while stopping \"{0}\": {1}", app.File, ex.ToString());
+ }
+ finally
+ {
+ if (AppRemoved != null)
+ AppRemoved(app.File);
+ app.Dispose();
+ }
+
+ }
+ AppList.Clear();
+ }
+ }
+ #endregion
+
+ public static void Write(string App, string Text)
+ {
+ // Check if it is a commands
+ bool isCommand = Command.Process(App, Text);
+
+ // Write to stdInput of app
+ if (!isCommand && AppList.ContainsKey(App))
+ AppList[App].Write(Text);
+ }
+
+ public static void WriteLine(string App, string Text)
+ {
+ // Check if it is a commands
+ bool isCommand = Command.Process(App, Text);
+
+ // Write to stdInput of app
+ if (!isCommand && AppList.ContainsKey(App))
+ AppList[App].WriteLine(Text);
+ }
+ }
+}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/Properties/AssemblyInfo.cs b/OpenSim/Tools/OpenSim.GridLaunch/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..4c300d0
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/Properties/AssemblyInfo.cs
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("OpenSim.GridLaunch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("OpenSim.GridLaunch")]
+[assembly: AssemblyCopyright("Copyright (c) 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("5072e919-46ab-47e6-8a63-08108324ccdf")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/Properties/Resources.Designer.cs b/OpenSim/Tools/OpenSim.GridLaunch/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..88b0ceb
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/Properties/Resources.Designer.cs
@@ -0,0 +1,84 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.3053
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace OpenSim.GridLaunch.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OpenSim.GridLaunch.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ internal static System.Drawing.Bitmap OpenSim {
+ get {
+ object obj = ResourceManager.GetObject("OpenSim", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ internal static System.Drawing.Bitmap OpenSim_Bottom_Border {
+ get {
+ object obj = ResourceManager.GetObject("OpenSim_Bottom_Border", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ internal static System.Drawing.Bitmap OpenSim_Right_Border {
+ get {
+ object obj = ResourceManager.GetObject("OpenSim_Right_Border", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+ }
+}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/Properties/Resources.resx b/OpenSim/Tools/OpenSim.GridLaunch/Properties/Resources.resx
new file mode 100644
index 0000000..b82a1fc
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/Properties/Resources.resx
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ ..\gui\winform\opensim.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\gui\winform\opensim bottom border.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\gui\winform\opensim right border.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
\ No newline at end of file
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/Settings.cs b/OpenSim/Tools/OpenSim.GridLaunch/Settings.cs
new file mode 100644
index 0000000..91353d8
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/Settings.cs
@@ -0,0 +1,181 @@
+/*
+ * 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.
+ */
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+using log4net;
+
+namespace OpenSim.GridLaunch
+{
+ internal class Settings
+ {
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private Dictionary Config = new Dictionary();
+ public Dictionary Components = new Dictionary();
+
+ public static string[] defaultComponents = new string[]
+ {
+ "OpenSim.Grid.UserServer.exe",
+ "OpenSim.Grid.GridServer.exe",
+ "OpenSim.Grid.AssetServer.exe",
+ "OpenSim.Grid.InventoryServer.exe",
+ "OpenSim.Grid.MessagingServer.exe",
+ "OpenSim.32BitLaunch.exe"
+ };
+
+
+ private static readonly char[] confSplit = new char[] { '=' };
+ private static readonly char[] comaSplit = new char[] { ',' };
+ private static readonly char[] colonSplit = new char[] { ';' };
+
+ private string configFile = "";
+
+ public Settings()
+ {
+ }
+ public Settings(string ConfigFile)
+ {
+ LoadConfig(ConfigFile);
+ }
+
+
+ public void LoadConfig(string ConfigFile)
+ {
+ configFile = ConfigFile;
+ m_log.Info("Reading config file: " + ConfigFile);
+ try
+ {
+ // Read config file
+ foreach (string line in System.IO.File.ReadAllLines(ConfigFile))
+ {
+ string[] s = line.Split(confSplit, 2);
+ if (s.Length >= 2)
+ Config.Add(s[0], s[1]);
+ }
+
+ // Process Components section
+ string cmp = Config["Components"];
+ Config.Remove("Components");
+ foreach (string c in cmp.Split(comaSplit))
+ {
+ string[] cs = c.Split(colonSplit);
+ if (cs.Length >= 2)
+ {
+ bool status = false;
+ bool.TryParse(cs[1], out status);
+ Components.Add(cs[0], status);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ m_log.Error("Exception reading config file: " + ex.ToString());
+ }
+ // No components? Add default components
+ if (Components.Count == 0)
+ foreach (string c in defaultComponents)
+ {
+ Components.Add(c, true);
+ }
+ }
+
+ public void SaveConfig(string ConfigFile)
+ {
+ configFile = ConfigFile;
+ SaveConfig();
+ }
+
+ public void SaveConfig()
+ {
+ m_log.Info("Writing config file: " + configFile);
+ try
+ {
+ System.IO.File.WriteAllText(configFile, ToString());
+ }
+ catch (Exception ex)
+ {
+ m_log.Error("Exception writing config file: " + ex.ToString());
+ }
+
+ }
+
+ public new string ToString()
+ {
+ StringBuilder ret = new StringBuilder();
+
+ Dictionary config = new Dictionary(Config);
+
+ // Add Components key
+ StringBuilder _Components = new StringBuilder();
+ foreach (string c in Components.Keys)
+ {
+ if (_Components.Length > 0)
+ _Components.Append(",");
+ _Components.Append(c + ";" + Components[c].ToString());
+ }
+ config["Components"] = _Components.ToString();
+
+ // Make return string
+ foreach (string key in config.Keys)
+ {
+ ret.AppendLine(key + "=" + config[key]);
+ }
+
+ // Return it
+ return ret.ToString();
+ }
+
+ public string this[string Key]
+ {
+ get
+ {
+ if (Config.ContainsKey(Key))
+ return Config[Key];
+ return "";
+ }
+ set { Config[Key] = value; }
+ }
+
+ public void ParseCommandArguments(string[] args)
+ {
+ string key = null;
+ foreach (string a in args)
+ {
+ if (a.StartsWith("--"))
+ key = a.Remove(0, 2);
+ else
+ {
+ if (key != null)
+ Config[key] = a;
+ key = null;
+ }
+ }
+
+ }
+ }
+}
diff --git a/OpenSim/Tools/OpenSim.GridLaunch/log4netAppender.cs b/OpenSim/Tools/OpenSim.GridLaunch/log4netAppender.cs
new file mode 100644
index 0000000..d9bea1a
--- /dev/null
+++ b/OpenSim/Tools/OpenSim.GridLaunch/log4netAppender.cs
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using log4net.Appender;
+using log4net.Core;
+
+namespace OpenSim.GridLaunch
+{
+ internal class log4netAppender : log4net.Appender.AppenderSkeleton
+ {
+ public delegate void LogLineDelegate(Color color, string Text);
+ public static event LogLineDelegate LogLine;
+ public static readonly Dictionary Level2Color = new Dictionary();
+
+ static log4netAppender()
+ {
+ Level2Color.Add("INFO", Color.Black);
+ Level2Color.Add("DEBUG", Color.Gray);
+ Level2Color.Add("WARN", Color.OrangeRed);
+ Level2Color.Add("ERROR", Color.Red);
+ }
+
+
+ protected override void Append(LoggingEvent loggingEvent)
+ {
+ // Find appropriate color
+ Color color = Color.Black;
+ if (Level2Color.ContainsKey(loggingEvent.Level.Name))
+ color = Level2Color[loggingEvent.Level.Name];
+
+ // Fire event with new log message
+ if (LogLine != null)
+ LogLine(color, loggingEvent.RenderedMessage + System.Environment.NewLine);
+ }
+
+ }
+}
--
cgit v1.1