233 lines
10 KiB
C#
233 lines
10 KiB
C#
/*
|
|
* Copyright (c) Contributors, http://www.openmetaverse.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.
|
|
*
|
|
*/
|
|
/* Original code: Tedd Hansen */
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Reflection;
|
|
|
|
namespace OpenSim.Region.ScriptEngine.DotNetEngine
|
|
{
|
|
class ScriptManager
|
|
{
|
|
|
|
private ScriptEngine myScriptEngine;
|
|
public ScriptManager(ScriptEngine _ScriptEngine)
|
|
{
|
|
myScriptEngine = _ScriptEngine;
|
|
Common.SendToDebug("ScriptManager Start");
|
|
}
|
|
|
|
|
|
// Object<string, Script<string, script>>
|
|
internal Dictionary<string, Dictionary<string, OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass>> Scripts = new Dictionary<string, Dictionary<string, OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass>>();
|
|
|
|
|
|
internal Dictionary<string, OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass>.KeyCollection GetScriptKeys(string ObjectID)
|
|
{
|
|
if (Scripts.ContainsKey(ObjectID) == false)
|
|
return null;
|
|
|
|
Dictionary<string, OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass> Obj;
|
|
Scripts.TryGetValue(ObjectID, out Obj);
|
|
|
|
return Obj.Keys;
|
|
|
|
}
|
|
|
|
internal OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass GetScript(string ObjectID, string ScriptID)
|
|
{
|
|
if (Scripts.ContainsKey(ObjectID) == false)
|
|
return null;
|
|
|
|
Dictionary<string, OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass> Obj;
|
|
Scripts.TryGetValue(ObjectID, out Obj);
|
|
if (Obj.ContainsKey(ScriptID) == false)
|
|
return null;
|
|
|
|
// Get script
|
|
OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass Script;
|
|
Obj.TryGetValue(ScriptID, out Script);
|
|
|
|
return Script;
|
|
|
|
}
|
|
internal void SetScript(string ObjectID, string ScriptID, OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass Script)
|
|
{
|
|
// Create object if it doesn't exist
|
|
if (Scripts.ContainsKey(ObjectID) == false)
|
|
Scripts.Add(ObjectID, new Dictionary<string, OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass>());
|
|
|
|
// Delete script if it exists
|
|
Dictionary<string, OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass> Obj;
|
|
Scripts.TryGetValue(ObjectID, out Obj);
|
|
if (Obj.ContainsKey(ScriptID) == true)
|
|
Obj.Remove(ScriptID);
|
|
|
|
// Add to object
|
|
Obj.Add(ScriptID, Script);
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fetches, loads and hooks up a script to an objects events
|
|
/// </summary>
|
|
/// <param name="ScriptID"></param>
|
|
/// <param name="ObjectID"></param>
|
|
public void StartScript(string ScriptID, string ObjectID)
|
|
{
|
|
Common.SendToDebug("ScriptManager StartScript: ScriptID: " + ScriptID + ", ObjectID: " + ObjectID);
|
|
|
|
// We will initialize and start the script.
|
|
// It will be up to the script itself to hook up the correct events.
|
|
string FileName;
|
|
|
|
// * Fetch script from server
|
|
// DEBUG - ScriptID is an actual filename during debug
|
|
// (therefore we can also check type by looking at extension)
|
|
FileName = ScriptID;
|
|
|
|
// * Does script need compile? Send it to LSL compiler first. (TODO: Use (and clean) compiler cache)
|
|
if (FileName.ToLower().EndsWith(".lso"))
|
|
{
|
|
Common.SendToDebug("ScriptManager Script is LSO, compiling to .Net Assembly");
|
|
// Create a new instance of the compiler (currently we don't want reuse)
|
|
OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.Engine LSLCompiler = new OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.Engine();
|
|
// Compile
|
|
FileName = LSLCompiler.Compile(FileName);
|
|
}
|
|
|
|
// * Insert yield into code
|
|
FileName = ProcessYield(FileName);
|
|
|
|
// * Find next available AppDomain to put it in
|
|
AppDomain FreeAppDomain = GetFreeAppDomain();
|
|
|
|
// * Load and start script
|
|
OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass Script = LoadAndInitAssembly(FreeAppDomain, FileName);
|
|
string FullScriptID = ScriptID + "." + ObjectID;
|
|
// Add it to our temporary active script keeper
|
|
//Scripts.Add(FullScriptID, Script);
|
|
SetScript(ObjectID, ScriptID, Script);
|
|
// We need to give (untrusted) assembly a private instance of BuiltIns
|
|
// this private copy will contain Read-Only FullScriptID so that it can bring that on to the server whenever needed.
|
|
OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BuiltIn_Commands_Interface LSLB = new OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BuiltIn_Commands_TestImplementation(FullScriptID);
|
|
// Start the script - giving it BuiltIns
|
|
Common.SendToDebug("ScriptManager initializing script, handing over private builtin command interface");
|
|
Script.Start(LSLB);
|
|
|
|
|
|
}
|
|
private string ProcessYield(string FileName)
|
|
{
|
|
// TODO: Create a new assembly and copy old but insert Yield Code
|
|
return FileName;
|
|
}
|
|
|
|
private AppDomain GetFreeAppDomain()
|
|
{
|
|
// TODO: Find an available AppDomain - if none, create one and add default security
|
|
return Thread.GetDomain();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Does actual loading and initialization of script Assembly
|
|
/// </summary>
|
|
/// <param name="FreeAppDomain">AppDomain to load script into</param>
|
|
/// <param name="FileName">FileName of script assembly (.dll)</param>
|
|
/// <returns></returns>
|
|
private OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass LoadAndInitAssembly(AppDomain FreeAppDomain, string FileName)
|
|
{
|
|
Common.SendToDebug("ScriptManager Loading Assembly " + FileName);
|
|
// Load .Net Assembly (.dll)
|
|
// Initialize and return it
|
|
|
|
// TODO: Add error handling
|
|
// Script might not follow our rules since users can upload -anything-
|
|
|
|
Assembly a;
|
|
//try
|
|
//{
|
|
|
|
|
|
// Load to default appdomain (temporary)
|
|
a = Assembly.LoadFrom(FileName);
|
|
// Load to specified appdomain
|
|
// TODO: Insert security
|
|
//a = FreeAppDomain.Load(FileName);
|
|
//}
|
|
//catch (Exception e)
|
|
//{
|
|
//}
|
|
|
|
|
|
foreach (Type _t in a.GetTypes())
|
|
{
|
|
Console.WriteLine("Type: " + _t.ToString());
|
|
}
|
|
|
|
Type t;
|
|
//try
|
|
//{
|
|
t = a.GetType("LSL_ScriptObject", true);
|
|
//}
|
|
//catch (Exception e)
|
|
//{
|
|
//}
|
|
|
|
return (OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass)Activator.CreateInstance(t);
|
|
|
|
|
|
}
|
|
|
|
internal void ExecuteFunction(string ObjectID, string ScriptID, string FunctionName, object[] args)
|
|
{
|
|
Common.SendToDebug("Executing Function ObjectID: " + ObjectID + ", ScriptID: " + ScriptID + ", FunctionName: " + FunctionName);
|
|
OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass Script = myScriptEngine.myScriptManager.GetScript(ObjectID, ScriptID);
|
|
|
|
Type type = Script.GetType();
|
|
//object o = (object)Script;
|
|
|
|
//System.Collections.Generic.List<string> Functions = (System.Collections.Generic.List<string>)
|
|
//Type type = typeof(OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass);
|
|
Common.SendToDebug("Invoke: \"" + Script.State + "_event_" + FunctionName + "\"");
|
|
type.InvokeMember(Script.State + "_event_" + FunctionName, BindingFlags.InvokeMethod, null, Script, args);
|
|
//System.Collections.Generic.List<string> Functions = (System.Collections.Generic.List<string>)type.InvokeMember("GetFunctions", BindingFlags.InvokeMethod, null, Script, null);
|
|
|
|
|
|
//foreach (MemberInfo mi in type.GetMembers())
|
|
//{
|
|
// Common.SendToDebug("Member found: " + mi.ToString());
|
|
//}
|
|
|
|
}
|
|
|
|
}
|
|
}
|