Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
commit
b430c0162c
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors
|
||||||
|
* 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.Reflection;
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Framework.Interfaces
|
||||||
|
{
|
||||||
|
public delegate void TakeValueCallback(string s);
|
||||||
|
|
||||||
|
public interface IJsonStoreModule
|
||||||
|
{
|
||||||
|
bool CreateStore(string value, out UUID result);
|
||||||
|
bool DestroyStore(UUID storeID);
|
||||||
|
bool TestPath(UUID storeID, string path, bool useJson);
|
||||||
|
bool SetValue(UUID storeID, string path, string value, bool useJson);
|
||||||
|
bool RemoveValue(UUID storeID, string path);
|
||||||
|
bool GetValue(UUID storeID, string path, bool useJson, out string value);
|
||||||
|
|
||||||
|
void TakeValue(UUID storeID, string path, bool useJson, TakeValueCallback cback);
|
||||||
|
void ReadValue(UUID storeID, string path, bool useJson, TakeValueCallback cback);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,500 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors
|
||||||
|
* 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 Mono.Addins;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Text;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
|
{
|
||||||
|
public class JsonStore
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log =
|
||||||
|
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private OSD m_ValueStore;
|
||||||
|
|
||||||
|
protected class TakeValueCallbackClass
|
||||||
|
{
|
||||||
|
public string Path { get; set; }
|
||||||
|
public bool UseJson { get; set; }
|
||||||
|
public TakeValueCallback Callback { get; set; }
|
||||||
|
|
||||||
|
public TakeValueCallbackClass(string spath, bool usejson, TakeValueCallback cback)
|
||||||
|
{
|
||||||
|
Path = spath;
|
||||||
|
UseJson = usejson;
|
||||||
|
Callback = cback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<TakeValueCallbackClass> m_TakeStore;
|
||||||
|
protected List<TakeValueCallbackClass> m_ReadStore;
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public JsonStore() : this("") {}
|
||||||
|
|
||||||
|
public JsonStore(string value)
|
||||||
|
{
|
||||||
|
m_TakeStore = new List<TakeValueCallbackClass>();
|
||||||
|
m_ReadStore = new List<TakeValueCallbackClass>();
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(value))
|
||||||
|
m_ValueStore = new OSDMap();
|
||||||
|
else
|
||||||
|
m_ValueStore = OSDParser.DeserializeJson(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public bool TestPath(string expr, bool useJson)
|
||||||
|
{
|
||||||
|
Stack<string> path = ParsePathExpression(expr);
|
||||||
|
OSD result = ProcessPathExpression(m_ValueStore,path);
|
||||||
|
|
||||||
|
if (result == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (useJson || result.Type == OSDType.String)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public bool GetValue(string expr, out string value, bool useJson)
|
||||||
|
{
|
||||||
|
Stack<string> path = ParsePathExpression(expr);
|
||||||
|
OSD result = ProcessPathExpression(m_ValueStore,path);
|
||||||
|
return ConvertOutputValue(result,out value,useJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public bool RemoveValue(string expr)
|
||||||
|
{
|
||||||
|
return SetValueFromExpression(expr,null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public bool SetValue(string expr, string value, bool useJson)
|
||||||
|
{
|
||||||
|
OSD ovalue = useJson ? OSDParser.DeserializeJson(value) : new OSDString(value);
|
||||||
|
return SetValueFromExpression(expr,ovalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public bool TakeValue(string expr, bool useJson, TakeValueCallback cback)
|
||||||
|
{
|
||||||
|
Stack<string> path = ParsePathExpression(expr);
|
||||||
|
string pexpr = PathExpressionToKey(path);
|
||||||
|
|
||||||
|
OSD result = ProcessPathExpression(m_ValueStore,path);
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
m_TakeStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string value = String.Empty;
|
||||||
|
if (! ConvertOutputValue(result,out value,useJson))
|
||||||
|
{
|
||||||
|
// the structure does not match the request so i guess we'll wait
|
||||||
|
m_TakeStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetValueFromExpression(expr,null);
|
||||||
|
cback(value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public bool ReadValue(string expr, bool useJson, TakeValueCallback cback)
|
||||||
|
{
|
||||||
|
Stack<string> path = ParsePathExpression(expr);
|
||||||
|
string pexpr = PathExpressionToKey(path);
|
||||||
|
|
||||||
|
OSD result = ProcessPathExpression(m_ValueStore,path);
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
m_ReadStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string value = String.Empty;
|
||||||
|
if (! ConvertOutputValue(result,out value,useJson))
|
||||||
|
{
|
||||||
|
// the structure does not match the request so i guess we'll wait
|
||||||
|
m_ReadStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cback(value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected bool SetValueFromExpression(string expr, OSD ovalue)
|
||||||
|
{
|
||||||
|
Stack<string> path = ParsePathExpression(expr);
|
||||||
|
if (path.Count == 0)
|
||||||
|
{
|
||||||
|
m_ValueStore = ovalue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
string pkey = path.Pop();
|
||||||
|
string pexpr = PathExpressionToKey(path);
|
||||||
|
if (pexpr != "")
|
||||||
|
pexpr += ".";
|
||||||
|
|
||||||
|
OSD result = ProcessPathExpression(m_ValueStore,path);
|
||||||
|
if (result == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Regex aPattern = new Regex("\\[([0-9]+|\\+)\\]");
|
||||||
|
MatchCollection amatches = aPattern.Matches(pkey,0);
|
||||||
|
|
||||||
|
if (amatches.Count > 0)
|
||||||
|
{
|
||||||
|
if (result.Type != OSDType.Array)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
OSDArray amap = result as OSDArray;
|
||||||
|
|
||||||
|
Match match = amatches[0];
|
||||||
|
GroupCollection groups = match.Groups;
|
||||||
|
string akey = groups[1].Value;
|
||||||
|
|
||||||
|
if (akey == "+")
|
||||||
|
{
|
||||||
|
string npkey = String.Format("[{0}]",amap.Count);
|
||||||
|
|
||||||
|
amap.Add(ovalue);
|
||||||
|
InvokeNextCallback(pexpr + npkey);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int aval = Convert.ToInt32(akey);
|
||||||
|
if (0 <= aval && aval < amap.Count)
|
||||||
|
{
|
||||||
|
if (ovalue == null)
|
||||||
|
amap.RemoveAt(aval);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
amap[aval] = ovalue;
|
||||||
|
InvokeNextCallback(pexpr + pkey);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Regex hPattern = new Regex("{([^}]+)}");
|
||||||
|
MatchCollection hmatches = hPattern.Matches(pkey,0);
|
||||||
|
|
||||||
|
if (hmatches.Count > 0)
|
||||||
|
{
|
||||||
|
Match match = hmatches[0];
|
||||||
|
GroupCollection groups = match.Groups;
|
||||||
|
string hkey = groups[1].Value;
|
||||||
|
|
||||||
|
if (result is OSDMap)
|
||||||
|
{
|
||||||
|
OSDMap hmap = result as OSDMap;
|
||||||
|
if (ovalue != null)
|
||||||
|
{
|
||||||
|
hmap[hkey] = ovalue;
|
||||||
|
InvokeNextCallback(pexpr + pkey);
|
||||||
|
}
|
||||||
|
else if (hmap.ContainsKey(hkey))
|
||||||
|
hmap.Remove(hkey);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shouldn't get here if the path was checked correctly
|
||||||
|
m_log.WarnFormat("[JsonStore] invalid path expression");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected bool InvokeNextCallback(string pexpr)
|
||||||
|
{
|
||||||
|
// Process all of the reads that match the expression first
|
||||||
|
List<TakeValueCallbackClass> reads =
|
||||||
|
m_ReadStore.FindAll(delegate(TakeValueCallbackClass tb) { return pexpr.StartsWith(tb.Path); });
|
||||||
|
|
||||||
|
foreach (TakeValueCallbackClass readcb in reads)
|
||||||
|
{
|
||||||
|
m_ReadStore.Remove(readcb);
|
||||||
|
ReadValue(readcb.Path,readcb.UseJson,readcb.Callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process one take next
|
||||||
|
TakeValueCallbackClass takecb =
|
||||||
|
m_TakeStore.Find(delegate(TakeValueCallbackClass tb) { return pexpr.StartsWith(tb.Path); });
|
||||||
|
|
||||||
|
if (takecb != null)
|
||||||
|
{
|
||||||
|
m_TakeStore.Remove(takecb);
|
||||||
|
TakeValue(takecb.Path,takecb.UseJson,takecb.Callback);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Parse the path expression and put the components into a stack. We
|
||||||
|
/// use a stack because we process the path in inverse order later
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected static Stack<string> ParsePathExpression(string path)
|
||||||
|
{
|
||||||
|
Stack<string> m_path = new Stack<string>();
|
||||||
|
|
||||||
|
// add front and rear separators
|
||||||
|
path = "." + path + ".";
|
||||||
|
|
||||||
|
// add separators for quoted paths
|
||||||
|
Regex pass1 = new Regex("{[^}]+}");
|
||||||
|
path = pass1.Replace(path,".$0.",-1,0);
|
||||||
|
|
||||||
|
// add separators for array references
|
||||||
|
Regex pass2 = new Regex("(\\[[0-9]+\\]|\\[\\+\\])");
|
||||||
|
path = pass2.Replace(path,".$0.",-1,0);
|
||||||
|
|
||||||
|
// add quotes to bare identifier
|
||||||
|
Regex pass3 = new Regex("\\.([a-zA-Z]+)");
|
||||||
|
path = pass3.Replace(path,".{$1}",-1,0);
|
||||||
|
|
||||||
|
// remove extra separators
|
||||||
|
Regex pass4 = new Regex("\\.+");
|
||||||
|
path = pass4.Replace(path,".",-1,0);
|
||||||
|
|
||||||
|
Regex validate = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)+$");
|
||||||
|
if (validate.IsMatch(path))
|
||||||
|
{
|
||||||
|
Regex parser = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\]+)");
|
||||||
|
MatchCollection matches = parser.Matches(path,0);
|
||||||
|
foreach (Match match in matches)
|
||||||
|
m_path.Push(match.Groups[1].Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param>path is a stack where the top level of the path is at the bottom of the stack</param>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected static OSD ProcessPathExpression(OSD map, Stack<string> path)
|
||||||
|
{
|
||||||
|
if (path.Count == 0)
|
||||||
|
return map;
|
||||||
|
|
||||||
|
string pkey = path.Pop();
|
||||||
|
|
||||||
|
OSD rmap = ProcessPathExpression(map,path);
|
||||||
|
if (rmap == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// ---------- Check for an array index ----------
|
||||||
|
Regex aPattern = new Regex("\\[([0-9]+)\\]");
|
||||||
|
MatchCollection amatches = aPattern.Matches(pkey,0);
|
||||||
|
|
||||||
|
if (amatches.Count > 0)
|
||||||
|
{
|
||||||
|
if (rmap.Type != OSDType.Array)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[JsonStore] wrong type for key {2}, expecting {0}, got {1}",OSDType.Array,rmap.Type,pkey);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSDArray amap = rmap as OSDArray;
|
||||||
|
|
||||||
|
Match match = amatches[0];
|
||||||
|
GroupCollection groups = match.Groups;
|
||||||
|
string akey = groups[1].Value;
|
||||||
|
int aval = Convert.ToInt32(akey);
|
||||||
|
|
||||||
|
if (aval < amap.Count)
|
||||||
|
return (OSD) amap[aval];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Check for a hash index ----------
|
||||||
|
Regex hPattern = new Regex("{([^}]+)}");
|
||||||
|
MatchCollection hmatches = hPattern.Matches(pkey,0);
|
||||||
|
|
||||||
|
if (hmatches.Count > 0)
|
||||||
|
{
|
||||||
|
if (rmap.Type != OSDType.Map)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[JsonStore] wrong type for key {2}, expecting {0}, got {1}",OSDType.Map,rmap.Type,pkey);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSDMap hmap = rmap as OSDMap;
|
||||||
|
|
||||||
|
Match match = hmatches[0];
|
||||||
|
GroupCollection groups = match.Groups;
|
||||||
|
string hkey = groups[1].Value;
|
||||||
|
|
||||||
|
if (hmap.ContainsKey(hkey))
|
||||||
|
return (OSD) hmap[hkey];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shouldn't get here if the path was checked correctly
|
||||||
|
m_log.WarnFormat("[JsonStore] Path type (unknown) does not match the structure");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected static bool ConvertOutputValue(OSD result, out string value, bool useJson)
|
||||||
|
{
|
||||||
|
value = String.Empty;
|
||||||
|
|
||||||
|
// If we couldn't process the path
|
||||||
|
if (result == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (useJson)
|
||||||
|
{
|
||||||
|
// The path pointed to an intermediate hash structure
|
||||||
|
if (result.Type == OSDType.Map)
|
||||||
|
{
|
||||||
|
value = OSDParser.SerializeJsonString(result as OSDMap);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The path pointed to an intermediate hash structure
|
||||||
|
if (result.Type == OSDType.Array)
|
||||||
|
{
|
||||||
|
value = OSDParser.SerializeJsonString(result as OSDArray);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = "'" + result.AsString() + "'";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.Type == OSDType.String)
|
||||||
|
{
|
||||||
|
value = result.AsString();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected static string PathExpressionToKey(Stack<string> path)
|
||||||
|
{
|
||||||
|
if (path.Count == 0)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
string pkey = "";
|
||||||
|
foreach (string k in path)
|
||||||
|
pkey = (pkey == "") ? k : (k + "." + pkey);
|
||||||
|
|
||||||
|
return pkey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,430 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors
|
||||||
|
* 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 Mono.Addins;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Text;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
|
||||||
|
namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
|
{
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreModule")]
|
||||||
|
|
||||||
|
public class JsonStoreModule : INonSharedRegionModule, IJsonStoreModule
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log =
|
||||||
|
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private IConfig m_config = null;
|
||||||
|
private bool m_enabled = false;
|
||||||
|
private Scene m_scene = null;
|
||||||
|
|
||||||
|
private Dictionary<UUID,JsonStore> m_JsonValueStore;
|
||||||
|
private UUID m_sharedStore;
|
||||||
|
|
||||||
|
#region IRegionModule Members
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Name of this shared module is it's class name
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return this.GetType().Name; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Initialise this shared module
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="scene">this region is getting initialised</param>
|
||||||
|
/// <param name="source">nini config, we are not using this</param>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if ((m_config = config.Configs["JsonStore"]) == null)
|
||||||
|
{
|
||||||
|
// There is no configuration, the module is disabled
|
||||||
|
// m_log.InfoFormat("[JsonStore] no configuration info");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_enabled = m_config.GetBoolean("Enabled", m_enabled);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("[JsonStore] initialization error: {0}",e.Message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_enabled)
|
||||||
|
m_log.DebugFormat("[JsonStore] module is enabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// everything is loaded, perform post load configuration
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Nothing to do on close
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
if (m_enabled)
|
||||||
|
{
|
||||||
|
m_scene = scene;
|
||||||
|
m_scene.RegisterModuleInterface<IJsonStoreModule>(this);
|
||||||
|
|
||||||
|
m_sharedStore = UUID.Zero;
|
||||||
|
m_JsonValueStore = new Dictionary<UUID,JsonStore>();
|
||||||
|
m_JsonValueStore.Add(m_sharedStore,new JsonStore(""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
// need to remove all references to the scene in the subscription
|
||||||
|
// list to enable full garbage collection of the scene object
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Called when all modules have been added for a region. This is
|
||||||
|
/// where we hook up events
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (m_enabled) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ScriptInvocationInteface
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public bool CreateStore(string value, out UUID result)
|
||||||
|
{
|
||||||
|
result = UUID.Zero;
|
||||||
|
|
||||||
|
if (! m_enabled) return false;
|
||||||
|
|
||||||
|
UUID uuid = UUID.Random();
|
||||||
|
JsonStore map = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
map = new JsonStore(value);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[JsonStore] Unable to initialize store from {0}; {1}",value,e.Message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (m_JsonValueStore)
|
||||||
|
m_JsonValueStore.Add(uuid,map);
|
||||||
|
|
||||||
|
result = uuid;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public bool DestroyStore(UUID storeID)
|
||||||
|
{
|
||||||
|
if (! m_enabled) return false;
|
||||||
|
|
||||||
|
lock (m_JsonValueStore)
|
||||||
|
m_JsonValueStore.Remove(storeID);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public bool TestPath(UUID storeID, string path, bool useJson)
|
||||||
|
{
|
||||||
|
if (! m_enabled) return false;
|
||||||
|
|
||||||
|
JsonStore map = null;
|
||||||
|
lock (m_JsonValueStore)
|
||||||
|
{
|
||||||
|
if (! m_JsonValueStore.TryGetValue(storeID,out map))
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (map)
|
||||||
|
return map.TestPath(path,useJson);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[JsonStore] Path test failed for {0} in {1}; {2}",path,storeID,e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public bool SetValue(UUID storeID, string path, string value, bool useJson)
|
||||||
|
{
|
||||||
|
if (! m_enabled) return false;
|
||||||
|
|
||||||
|
JsonStore map = null;
|
||||||
|
lock (m_JsonValueStore)
|
||||||
|
{
|
||||||
|
if (! m_JsonValueStore.TryGetValue(storeID,out map))
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (map)
|
||||||
|
if (map.SetValue(path,value,useJson))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[JsonStore] Unable to assign {0} to {1} in {2}; {3}",value,path,storeID,e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public bool RemoveValue(UUID storeID, string path)
|
||||||
|
{
|
||||||
|
if (! m_enabled) return false;
|
||||||
|
|
||||||
|
JsonStore map = null;
|
||||||
|
lock (m_JsonValueStore)
|
||||||
|
{
|
||||||
|
if (! m_JsonValueStore.TryGetValue(storeID,out map))
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (map)
|
||||||
|
if (map.RemoveValue(path))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[JsonStore] Unable to remove {0} in {1}; {2}",path,storeID,e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public bool GetValue(UUID storeID, string path, bool useJson, out string value)
|
||||||
|
{
|
||||||
|
value = String.Empty;
|
||||||
|
|
||||||
|
if (! m_enabled) return false;
|
||||||
|
|
||||||
|
JsonStore map = null;
|
||||||
|
lock (m_JsonValueStore)
|
||||||
|
{
|
||||||
|
if (! m_JsonValueStore.TryGetValue(storeID,out map))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (map)
|
||||||
|
{
|
||||||
|
return map.GetValue(path, out value, useJson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void TakeValue(UUID storeID, string path, bool useJson, TakeValueCallback cback)
|
||||||
|
{
|
||||||
|
if (! m_enabled)
|
||||||
|
{
|
||||||
|
cback(String.Empty);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonStore map = null;
|
||||||
|
lock (m_JsonValueStore)
|
||||||
|
{
|
||||||
|
if (! m_JsonValueStore.TryGetValue(storeID,out map))
|
||||||
|
{
|
||||||
|
cback(String.Empty);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (map)
|
||||||
|
{
|
||||||
|
map.TakeValue(path, useJson, cback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
cback(String.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void ReadValue(UUID storeID, string path, bool useJson, TakeValueCallback cback)
|
||||||
|
{
|
||||||
|
if (! m_enabled)
|
||||||
|
{
|
||||||
|
cback(String.Empty);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonStore map = null;
|
||||||
|
lock (m_JsonValueStore)
|
||||||
|
{
|
||||||
|
if (! m_JsonValueStore.TryGetValue(storeID,out map))
|
||||||
|
{
|
||||||
|
cback(String.Empty);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (map)
|
||||||
|
{
|
||||||
|
map.ReadValue(path, useJson, cback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
cback(String.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,490 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors
|
||||||
|
* 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 Mono.Addins;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Text;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenMetaverse.StructuredData;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
|
{
|
||||||
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreScriptModule")]
|
||||||
|
|
||||||
|
public class JsonStoreScriptModule : INonSharedRegionModule
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log =
|
||||||
|
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private IConfig m_config = null;
|
||||||
|
private bool m_enabled = false;
|
||||||
|
private Scene m_scene = null;
|
||||||
|
|
||||||
|
private IScriptModuleComms m_comms;
|
||||||
|
private IJsonStoreModule m_store;
|
||||||
|
|
||||||
|
#region IRegionModule Members
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Name of this shared module is it's class name
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return this.GetType().Name; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Initialise this shared module
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="scene">this region is getting initialised</param>
|
||||||
|
/// <param name="source">nini config, we are not using this</param>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void Initialise(IConfigSource config)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if ((m_config = config.Configs["JsonStore"]) == null)
|
||||||
|
{
|
||||||
|
// There is no configuration, the module is disabled
|
||||||
|
// m_log.InfoFormat("[JsonStoreScripts] no configuration info");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_enabled = m_config.GetBoolean("Enabled", m_enabled);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("[JsonStoreScripts] initialization error: {0}",e.Message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_enabled)
|
||||||
|
m_log.DebugFormat("[JsonStoreScripts] module is enabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// everything is loaded, perform post load configuration
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void PostInitialise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Nothing to do on close
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void AddRegion(Scene scene)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void RemoveRegion(Scene scene)
|
||||||
|
{
|
||||||
|
// need to remove all references to the scene in the subscription
|
||||||
|
// list to enable full garbage collection of the scene object
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// Called when all modules have been added for a region. This is
|
||||||
|
/// where we hook up events
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (m_enabled)
|
||||||
|
{
|
||||||
|
m_scene = scene;
|
||||||
|
m_comms = m_scene.RequestModuleInterface<IScriptModuleComms>();
|
||||||
|
if (m_comms == null)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("[JsonStoreScripts] ScriptModuleComms interface not defined");
|
||||||
|
m_enabled = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_store = m_scene.RequestModuleInterface<IJsonStoreModule>();
|
||||||
|
if (m_store == null)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat("[JsonStoreScripts] JsonModule interface not defined");
|
||||||
|
m_enabled = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_comms.RegisterScriptInvocation(this,"JsonCreateStore");
|
||||||
|
m_comms.RegisterScriptInvocation(this,"JsonDestroyStore");
|
||||||
|
|
||||||
|
m_comms.RegisterScriptInvocation(this,"JsonReadNotecard");
|
||||||
|
m_comms.RegisterScriptInvocation(this,"JsonWriteNotecard");
|
||||||
|
|
||||||
|
m_comms.RegisterScriptInvocation(this,"JsonTestPath");
|
||||||
|
m_comms.RegisterScriptInvocation(this,"JsonTestPathJson");
|
||||||
|
|
||||||
|
m_comms.RegisterScriptInvocation(this,"JsonGetValue");
|
||||||
|
m_comms.RegisterScriptInvocation(this,"JsonGetValueJson");
|
||||||
|
|
||||||
|
m_comms.RegisterScriptInvocation(this,"JsonTakeValue");
|
||||||
|
m_comms.RegisterScriptInvocation(this,"JsonTakeValueJson");
|
||||||
|
|
||||||
|
m_comms.RegisterScriptInvocation(this,"JsonReadValue");
|
||||||
|
m_comms.RegisterScriptInvocation(this,"JsonReadValueJson");
|
||||||
|
|
||||||
|
m_comms.RegisterScriptInvocation(this,"JsonSetValue");
|
||||||
|
m_comms.RegisterScriptInvocation(this,"JsonSetValueJson");
|
||||||
|
|
||||||
|
m_comms.RegisterScriptInvocation(this,"JsonRemoveValue");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
public Type ReplaceableInterface
|
||||||
|
{
|
||||||
|
get { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ScriptInvocationInteface
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected void GenerateRuntimeError(string msg)
|
||||||
|
{
|
||||||
|
throw new Exception("JsonStore Runtime Error: " + msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value)
|
||||||
|
{
|
||||||
|
UUID uuid = UUID.Zero;
|
||||||
|
if (! m_store.CreateStore(value, out uuid))
|
||||||
|
GenerateRuntimeError("Failed to create Json store");
|
||||||
|
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID)
|
||||||
|
{
|
||||||
|
return m_store.DestroyStore(storeID) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected UUID JsonReadNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, UUID assetID)
|
||||||
|
{
|
||||||
|
UUID reqID = UUID.Random();
|
||||||
|
Util.FireAndForget(delegate(object o) { DoJsonReadNotecard(reqID,hostID,scriptID,storeID,path,assetID); });
|
||||||
|
return reqID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected UUID JsonWriteNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, string name)
|
||||||
|
{
|
||||||
|
UUID reqID = UUID.Random();
|
||||||
|
Util.FireAndForget(delegate(object o) { DoJsonWriteNotecard(reqID,hostID,scriptID,storeID,path,name); });
|
||||||
|
return reqID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path)
|
||||||
|
{
|
||||||
|
return m_store.TestPath(storeID,path,false) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int JsonTestPathJson(UUID hostID, UUID scriptID, UUID storeID, string path)
|
||||||
|
{
|
||||||
|
return m_store.TestPath(storeID,path,true) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected int JsonSetValue(UUID hostID, UUID scriptID, UUID storeID, string path, string value)
|
||||||
|
{
|
||||||
|
return m_store.SetValue(storeID,path,value,false) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int JsonSetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path, string value)
|
||||||
|
{
|
||||||
|
return m_store.SetValue(storeID,path,value,true) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected int JsonRemoveValue(UUID hostID, UUID scriptID, UUID storeID, string path)
|
||||||
|
{
|
||||||
|
return m_store.RemoveValue(storeID,path) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected string JsonGetValue(UUID hostID, UUID scriptID, UUID storeID, string path)
|
||||||
|
{
|
||||||
|
string value = String.Empty;
|
||||||
|
m_store.GetValue(storeID,path,false,out value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string JsonGetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
|
||||||
|
{
|
||||||
|
string value = String.Empty;
|
||||||
|
m_store.GetValue(storeID,path,true, out value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected UUID JsonTakeValue(UUID hostID, UUID scriptID, UUID storeID, string path)
|
||||||
|
{
|
||||||
|
UUID reqID = UUID.Random();
|
||||||
|
Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,false); });
|
||||||
|
return reqID;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected UUID JsonTakeValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
|
||||||
|
{
|
||||||
|
UUID reqID = UUID.Random();
|
||||||
|
Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,true); });
|
||||||
|
return reqID;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DoJsonTakeValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_store.TakeValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[JsonStoreScripts] unable to retrieve value; {0}",e.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchValue(scriptID,reqID,String.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected UUID JsonReadValue(UUID hostID, UUID scriptID, UUID storeID, string path)
|
||||||
|
{
|
||||||
|
UUID reqID = UUID.Random();
|
||||||
|
Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,false); });
|
||||||
|
return reqID;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected UUID JsonReadValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
|
||||||
|
{
|
||||||
|
UUID reqID = UUID.Random();
|
||||||
|
Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,true); });
|
||||||
|
return reqID;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DoJsonReadValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_store.ReadValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[JsonStoreScripts] unable to retrieve value; {0}",e.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchValue(scriptID,reqID,String.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
protected void DispatchValue(UUID scriptID, UUID reqID, string value)
|
||||||
|
{
|
||||||
|
m_comms.DispatchReply(scriptID,1,value,reqID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
private void DoJsonReadNotecard(UUID reqID, UUID hostID, UUID scriptID, UUID storeID, string path, UUID assetID)
|
||||||
|
{
|
||||||
|
AssetBase a = m_scene.AssetService.Get(assetID.ToString());
|
||||||
|
if (a == null)
|
||||||
|
GenerateRuntimeError(String.Format("Unable to find notecard asset {0}",assetID));
|
||||||
|
|
||||||
|
if (a.Type != (sbyte)AssetType.Notecard)
|
||||||
|
GenerateRuntimeError(String.Format("Invalid notecard asset {0}",assetID));
|
||||||
|
|
||||||
|
m_log.DebugFormat("[JsonStoreScripts] read notecard in context {0}",storeID);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
|
||||||
|
string jsondata = SLUtil.ParseNotecardToString(enc.GetString(a.Data));
|
||||||
|
int result = m_store.SetValue(storeID,path,jsondata,true) ? 1 : 0;
|
||||||
|
m_comms.DispatchReply(scriptID,result,"",reqID.ToString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[JsonStoreScripts] Json parsing failed; {0}",e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
GenerateRuntimeError(String.Format("Json parsing failed for {0}",assetID.ToString()));
|
||||||
|
m_comms.DispatchReply(scriptID,0,"",reqID.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
private void DoJsonWriteNotecard(UUID reqID, UUID hostID, UUID scriptID, UUID storeID, string path, string name)
|
||||||
|
{
|
||||||
|
string data;
|
||||||
|
if (! m_store.GetValue(storeID,path,true, out data))
|
||||||
|
{
|
||||||
|
m_comms.DispatchReply(scriptID,0,UUID.Zero.ToString(),reqID.ToString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneObjectPart host = m_scene.GetSceneObjectPart(hostID);
|
||||||
|
|
||||||
|
// Create new asset
|
||||||
|
UUID assetID = UUID.Random();
|
||||||
|
AssetBase asset = new AssetBase(assetID, name, (sbyte)AssetType.Notecard, host.OwnerID.ToString());
|
||||||
|
asset.Description = "Json store";
|
||||||
|
|
||||||
|
int textLength = data.Length;
|
||||||
|
data = "Linden text version 2\n{\nLLEmbeddedItems version 1\n{\ncount 0\n}\nText length "
|
||||||
|
+ textLength.ToString() + "\n" + data + "}\n";
|
||||||
|
|
||||||
|
asset.Data = Util.UTF8.GetBytes(data);
|
||||||
|
m_scene.AssetService.Store(asset);
|
||||||
|
|
||||||
|
// Create Task Entry
|
||||||
|
TaskInventoryItem taskItem = new TaskInventoryItem();
|
||||||
|
|
||||||
|
taskItem.ResetIDs(host.UUID);
|
||||||
|
taskItem.ParentID = host.UUID;
|
||||||
|
taskItem.CreationDate = (uint)Util.UnixTimeSinceEpoch();
|
||||||
|
taskItem.Name = asset.Name;
|
||||||
|
taskItem.Description = asset.Description;
|
||||||
|
taskItem.Type = (int)AssetType.Notecard;
|
||||||
|
taskItem.InvType = (int)InventoryType.Notecard;
|
||||||
|
taskItem.OwnerID = host.OwnerID;
|
||||||
|
taskItem.CreatorID = host.OwnerID;
|
||||||
|
taskItem.BasePermissions = (uint)PermissionMask.All;
|
||||||
|
taskItem.CurrentPermissions = (uint)PermissionMask.All;
|
||||||
|
taskItem.EveryonePermissions = 0;
|
||||||
|
taskItem.NextPermissions = (uint)PermissionMask.All;
|
||||||
|
taskItem.GroupID = host.GroupID;
|
||||||
|
taskItem.GroupPermissions = 0;
|
||||||
|
taskItem.Flags = 0;
|
||||||
|
taskItem.PermsGranter = UUID.Zero;
|
||||||
|
taskItem.PermsMask = 0;
|
||||||
|
taskItem.AssetID = asset.FullID;
|
||||||
|
|
||||||
|
host.Inventory.AddInventoryItem(taskItem, false);
|
||||||
|
|
||||||
|
m_comms.DispatchReply(scriptID,1,assetID.ToString(),reqID.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,7 +38,7 @@ using OpenMetaverse;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
|
namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
|
||||||
{
|
{
|
||||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")]
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")]
|
||||||
class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms
|
class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms
|
||||||
|
|
|
@ -1560,6 +1560,12 @@
|
||||||
MaptileURL = "http://www.mygrid.com/Grid/"
|
MaptileURL = "http://www.mygrid.com/Grid/"
|
||||||
RefreshTime = 3600
|
RefreshTime = 3600
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; JsonStore module provides structured store for scripts
|
||||||
|
;;
|
||||||
|
[JsonStore]
|
||||||
|
Enabled = False
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;; These are defaults that are overwritten below in [Architecture].
|
;; These are defaults that are overwritten below in [Architecture].
|
||||||
;; These defaults allow OpenSim to work out of the box with
|
;; These defaults allow OpenSim to work out of the box with
|
||||||
|
|
Loading…
Reference in New Issue