aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/Scripting/JsonStore
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/OptionalModules/Scripting/JsonStore')
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs498
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs429
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs489
3 files changed, 1416 insertions, 0 deletions
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
new file mode 100644
index 0000000..49556b6
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
@@ -0,0 +1,498 @@
1/*
2 * Copyright (c) Contributors
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using Mono.Addins;
28
29using System;
30using System.Reflection;
31using System.Threading;
32using System.Text;
33using System.Net;
34using System.Net.Sockets;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42using System.Collections.Generic;
43using System.Text.RegularExpressions;
44
45namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
46{
47 public class JsonStore
48 {
49 private static readonly ILog m_log =
50 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 private OSD m_ValueStore;
53
54 protected class TakeValueCallbackClass
55 {
56 public string Path { get; set; }
57 public bool UseJson { get; set; }
58 public TakeValueCallback Callback { get; set; }
59
60 public TakeValueCallbackClass(string spath, bool usejson, TakeValueCallback cback)
61 {
62 Path = spath;
63 UseJson = usejson;
64 Callback = cback;
65 }
66 }
67
68 protected List<TakeValueCallbackClass> m_TakeStore;
69 protected List<TakeValueCallbackClass> m_ReadStore;
70
71
72 // -----------------------------------------------------------------
73 /// <summary>
74 ///
75 /// </summary>
76 // -----------------------------------------------------------------
77 public JsonStore(string value = "")
78 {
79 m_TakeStore = new List<TakeValueCallbackClass>();
80 m_ReadStore = new List<TakeValueCallbackClass>();
81
82 if (String.IsNullOrEmpty(value))
83 m_ValueStore = new OSDMap();
84 else
85 m_ValueStore = OSDParser.DeserializeJson(value);
86 }
87
88 // -----------------------------------------------------------------
89 /// <summary>
90 ///
91 /// </summary>
92 // -----------------------------------------------------------------
93 public bool TestPath(string expr, bool useJson)
94 {
95 Stack<string> path = ParsePathExpression(expr);
96 OSD result = ProcessPathExpression(m_ValueStore,path);
97
98 if (result == null)
99 return false;
100
101 if (useJson || result.Type == OSDType.String)
102 return true;
103
104 return false;
105 }
106
107 // -----------------------------------------------------------------
108 /// <summary>
109 ///
110 /// </summary>
111 // -----------------------------------------------------------------
112 public bool GetValue(string expr, out string value, bool useJson)
113 {
114 Stack<string> path = ParsePathExpression(expr);
115 OSD result = ProcessPathExpression(m_ValueStore,path);
116 return ConvertOutputValue(result,out value,useJson);
117 }
118
119
120 // -----------------------------------------------------------------
121 /// <summary>
122 ///
123 /// </summary>
124 // -----------------------------------------------------------------
125 public bool RemoveValue(string expr)
126 {
127 return SetValueFromExpression(expr,null);
128 }
129
130 // -----------------------------------------------------------------
131 /// <summary>
132 ///
133 /// </summary>
134 // -----------------------------------------------------------------
135 public bool SetValue(string expr, string value, bool useJson)
136 {
137 OSD ovalue = useJson ? OSDParser.DeserializeJson(value) : new OSDString(value);
138 return SetValueFromExpression(expr,ovalue);
139 }
140
141 // -----------------------------------------------------------------
142 /// <summary>
143 ///
144 /// </summary>
145 // -----------------------------------------------------------------
146 public bool TakeValue(string expr, bool useJson, TakeValueCallback cback)
147 {
148 Stack<string> path = ParsePathExpression(expr);
149 string pexpr = PathExpressionToKey(path);
150
151 OSD result = ProcessPathExpression(m_ValueStore,path);
152 if (result == null)
153 {
154 m_TakeStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
155 return false;
156 }
157
158 string value = String.Empty;
159 if (! ConvertOutputValue(result,out value,useJson))
160 {
161 // the structure does not match the request so i guess we'll wait
162 m_TakeStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
163 return false;
164 }
165
166 SetValueFromExpression(expr,null);
167 cback(value);
168
169 return true;
170 }
171
172 // -----------------------------------------------------------------
173 /// <summary>
174 ///
175 /// </summary>
176 // -----------------------------------------------------------------
177 public bool ReadValue(string expr, bool useJson, TakeValueCallback cback)
178 {
179 Stack<string> path = ParsePathExpression(expr);
180 string pexpr = PathExpressionToKey(path);
181
182 OSD result = ProcessPathExpression(m_ValueStore,path);
183 if (result == null)
184 {
185 m_ReadStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
186 return false;
187 }
188
189 string value = String.Empty;
190 if (! ConvertOutputValue(result,out value,useJson))
191 {
192 // the structure does not match the request so i guess we'll wait
193 m_ReadStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
194 return false;
195 }
196
197 cback(value);
198
199 return true;
200 }
201
202 // -----------------------------------------------------------------
203 /// <summary>
204 ///
205 /// </summary>
206 // -----------------------------------------------------------------
207 protected bool SetValueFromExpression(string expr, OSD ovalue)
208 {
209 Stack<string> path = ParsePathExpression(expr);
210 if (path.Count == 0)
211 {
212 m_ValueStore = ovalue;
213 return true;
214 }
215
216 string pkey = path.Pop();
217 string pexpr = PathExpressionToKey(path);
218 if (pexpr != "")
219 pexpr += ".";
220
221 OSD result = ProcessPathExpression(m_ValueStore,path);
222 if (result == null)
223 return false;
224
225 Regex aPattern = new Regex("\\[([0-9]+|\\+)\\]");
226 MatchCollection amatches = aPattern.Matches(pkey,0);
227
228 if (amatches.Count > 0)
229 {
230 if (result.Type != OSDType.Array)
231 return false;
232
233 OSDArray amap = result as OSDArray;
234
235 Match match = amatches[0];
236 GroupCollection groups = match.Groups;
237 string akey = groups[1].Value;
238
239 if (akey == "+")
240 {
241 string npkey = String.Format("[{0}]",amap.Count);
242
243 amap.Add(ovalue);
244 InvokeNextCallback(pexpr + npkey);
245 return true;
246 }
247
248 int aval = Convert.ToInt32(akey);
249 if (0 <= aval && aval < amap.Count)
250 {
251 if (ovalue == null)
252 amap.RemoveAt(aval);
253 else
254 {
255 amap[aval] = ovalue;
256 InvokeNextCallback(pexpr + pkey);
257 }
258 return true;
259 }
260
261 return false;
262 }
263
264 Regex hPattern = new Regex("{([^}]+)}");
265 MatchCollection hmatches = hPattern.Matches(pkey,0);
266
267 if (hmatches.Count > 0)
268 {
269 Match match = hmatches[0];
270 GroupCollection groups = match.Groups;
271 string hkey = groups[1].Value;
272
273 if (result is OSDMap)
274 {
275 OSDMap hmap = result as OSDMap;
276 if (ovalue != null)
277 {
278 hmap[hkey] = ovalue;
279 InvokeNextCallback(pexpr + pkey);
280 }
281 else if (hmap.ContainsKey(hkey))
282 hmap.Remove(hkey);
283
284 return true;
285 }
286
287 return false;
288 }
289
290 // Shouldn't get here if the path was checked correctly
291 m_log.WarnFormat("[JsonStore] invalid path expression");
292 return false;
293 }
294
295 // -----------------------------------------------------------------
296 /// <summary>
297 ///
298 /// </summary>
299 // -----------------------------------------------------------------
300 protected bool InvokeNextCallback(string pexpr)
301 {
302 // Process all of the reads that match the expression first
303 List<TakeValueCallbackClass> reads =
304 m_ReadStore.FindAll(delegate(TakeValueCallbackClass tb) { return pexpr.StartsWith(tb.Path); });
305
306 foreach (TakeValueCallbackClass readcb in reads)
307 {
308 m_ReadStore.Remove(readcb);
309 ReadValue(readcb.Path,readcb.UseJson,readcb.Callback);
310 }
311
312 // Process one take next
313 TakeValueCallbackClass takecb =
314 m_TakeStore.Find(delegate(TakeValueCallbackClass tb) { return pexpr.StartsWith(tb.Path); });
315
316 if (takecb != null)
317 {
318 m_TakeStore.Remove(takecb);
319 TakeValue(takecb.Path,takecb.UseJson,takecb.Callback);
320
321 return true;
322 }
323
324 return false;
325 }
326
327 // -----------------------------------------------------------------
328 /// <summary>
329 /// Parse the path expression and put the components into a stack. We
330 /// use a stack because we process the path in inverse order later
331 /// </summary>
332 // -----------------------------------------------------------------
333 protected static Stack<string> ParsePathExpression(string path)
334 {
335 Stack<string> m_path = new Stack<string>();
336
337 // add front and rear separators
338 path = "." + path + ".";
339
340 // add separators for quoted paths
341 Regex pass1 = new Regex("{[^}]+}");
342 path = pass1.Replace(path,".$0.",-1,0);
343
344 // add separators for array references
345 Regex pass2 = new Regex("(\\[[0-9]+\\]|\\[\\+\\])");
346 path = pass2.Replace(path,".$0.",-1,0);
347
348 // add quotes to bare identifier
349 Regex pass3 = new Regex("\\.([a-zA-Z]+)");
350 path = pass3.Replace(path,".{$1}",-1,0);
351
352 // remove extra separators
353 Regex pass4 = new Regex("\\.+");
354 path = pass4.Replace(path,".",-1,0);
355
356 Regex validate = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)+$");
357 if (validate.IsMatch(path))
358 {
359 Regex parser = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\]+)");
360 MatchCollection matches = parser.Matches(path,0);
361 foreach (Match match in matches)
362 m_path.Push(match.Groups[1].Value);
363 }
364
365 return m_path;
366 }
367
368 // -----------------------------------------------------------------
369 /// <summary>
370 ///
371 /// </summary>
372 /// <param>path is a stack where the top level of the path is at the bottom of the stack</param>
373 // -----------------------------------------------------------------
374 protected static OSD ProcessPathExpression(OSD map, Stack<string> path)
375 {
376 if (path.Count == 0)
377 return map;
378
379 string pkey = path.Pop();
380
381 OSD rmap = ProcessPathExpression(map,path);
382 if (rmap == null)
383 return null;
384
385 // ---------- Check for an array index ----------
386 Regex aPattern = new Regex("\\[([0-9]+)\\]");
387 MatchCollection amatches = aPattern.Matches(pkey,0);
388
389 if (amatches.Count > 0)
390 {
391 if (rmap.Type != OSDType.Array)
392 {
393 m_log.WarnFormat("[JsonStore] wrong type for key {2}, expecting {0}, got {1}",OSDType.Array,rmap.Type,pkey);
394 return null;
395 }
396
397 OSDArray amap = rmap as OSDArray;
398
399 Match match = amatches[0];
400 GroupCollection groups = match.Groups;
401 string akey = groups[1].Value;
402 int aval = Convert.ToInt32(akey);
403
404 if (aval < amap.Count)
405 return (OSD) amap[aval];
406
407 return null;
408 }
409
410 // ---------- Check for a hash index ----------
411 Regex hPattern = new Regex("{([^}]+)}");
412 MatchCollection hmatches = hPattern.Matches(pkey,0);
413
414 if (hmatches.Count > 0)
415 {
416 if (rmap.Type != OSDType.Map)
417 {
418 m_log.WarnFormat("[JsonStore] wrong type for key {2}, expecting {0}, got {1}",OSDType.Map,rmap.Type,pkey);
419 return null;
420 }
421
422 OSDMap hmap = rmap as OSDMap;
423
424 Match match = hmatches[0];
425 GroupCollection groups = match.Groups;
426 string hkey = groups[1].Value;
427
428 if (hmap.ContainsKey(hkey))
429 return (OSD) hmap[hkey];
430
431 return null;
432 }
433
434 // Shouldn't get here if the path was checked correctly
435 m_log.WarnFormat("[JsonStore] Path type (unknown) does not match the structure");
436 return null;
437 }
438
439 // -----------------------------------------------------------------
440 /// <summary>
441 ///
442 /// </summary>
443 // -----------------------------------------------------------------
444 protected static bool ConvertOutputValue(OSD result, out string value, bool useJson)
445 {
446 value = String.Empty;
447
448 // If we couldn't process the path
449 if (result == null)
450 return false;
451
452 if (useJson)
453 {
454 // The path pointed to an intermediate hash structure
455 if (result.Type == OSDType.Map)
456 {
457 value = OSDParser.SerializeJsonString(result as OSDMap);
458 return true;
459 }
460
461 // The path pointed to an intermediate hash structure
462 if (result.Type == OSDType.Array)
463 {
464 value = OSDParser.SerializeJsonString(result as OSDArray);
465 return true;
466 }
467
468 value = "'" + result.AsString() + "'";
469 return true;
470 }
471
472 if (result.Type == OSDType.String)
473 {
474 value = result.AsString();
475 return true;
476 }
477
478 return false;
479 }
480
481 // -----------------------------------------------------------------
482 /// <summary>
483 ///
484 /// </summary>
485 // -----------------------------------------------------------------
486 protected static string PathExpressionToKey(Stack<string> path)
487 {
488 if (path.Count == 0)
489 return "";
490
491 string pkey = "";
492 foreach (string k in path)
493 pkey = (pkey == "") ? k : (k + "." + pkey);
494
495 return pkey;
496 }
497 }
498}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
new file mode 100644
index 0000000..6dae956
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
@@ -0,0 +1,429 @@
1/*
2 * Copyright (c) Contributors
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using Mono.Addins;
28
29using System;
30using System.Reflection;
31using System.Threading;
32using System.Text;
33using System.Net;
34using System.Net.Sockets;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42using System.Collections.Generic;
43using System.Text.RegularExpressions;
44
45
46namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
47{
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreModule")]
49
50 public class JsonStoreModule : INonSharedRegionModule, IJsonStoreModule
51 {
52 private static readonly ILog m_log =
53 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54
55 private IConfig m_config = null;
56 private bool m_enabled = false;
57 private Scene m_scene = null;
58
59 private Dictionary<UUID,JsonStore> m_JsonValueStore;
60 private UUID m_sharedStore;
61
62#region IRegionModule Members
63
64 // -----------------------------------------------------------------
65 /// <summary>
66 /// Name of this shared module is it's class name
67 /// </summary>
68 // -----------------------------------------------------------------
69 public string Name
70 {
71 get { return this.GetType().Name; }
72 }
73
74 // -----------------------------------------------------------------
75 /// <summary>
76 /// Initialise this shared module
77 /// </summary>
78 /// <param name="scene">this region is getting initialised</param>
79 /// <param name="source">nini config, we are not using this</param>
80 // -----------------------------------------------------------------
81 public void Initialise(IConfigSource config)
82 {
83 try
84 {
85 if ((m_config = config.Configs["JsonStore"]) == null)
86 {
87 // There is no configuration, the module is disabled
88 m_log.InfoFormat("[JsonStore] no configuration info");
89 return;
90 }
91
92 m_enabled = m_config.GetBoolean("Enabled", m_enabled);
93 }
94 catch (Exception e)
95 {
96 m_log.ErrorFormat("[JsonStore] initialization error: {0}",e.Message);
97 return;
98 }
99
100 m_log.InfoFormat("[JsonStore] module {0} enabled",(m_enabled ? "is" : "is not"));
101 }
102
103 // -----------------------------------------------------------------
104 /// <summary>
105 /// everything is loaded, perform post load configuration
106 /// </summary>
107 // -----------------------------------------------------------------
108 public void PostInitialise()
109 {
110 }
111
112 // -----------------------------------------------------------------
113 /// <summary>
114 /// Nothing to do on close
115 /// </summary>
116 // -----------------------------------------------------------------
117 public void Close()
118 {
119 }
120
121 // -----------------------------------------------------------------
122 /// <summary>
123 /// </summary>
124 // -----------------------------------------------------------------
125 public void AddRegion(Scene scene)
126 {
127 if (m_enabled)
128 {
129 m_scene = scene;
130 m_scene.RegisterModuleInterface<IJsonStoreModule>(this);
131
132 m_sharedStore = UUID.Zero;
133 m_JsonValueStore = new Dictionary<UUID,JsonStore>();
134 m_JsonValueStore.Add(m_sharedStore,new JsonStore(""));
135 }
136 }
137
138 // -----------------------------------------------------------------
139 /// <summary>
140 /// </summary>
141 // -----------------------------------------------------------------
142 public void RemoveRegion(Scene scene)
143 {
144 // need to remove all references to the scene in the subscription
145 // list to enable full garbage collection of the scene object
146 }
147
148 // -----------------------------------------------------------------
149 /// <summary>
150 /// Called when all modules have been added for a region. This is
151 /// where we hook up events
152 /// </summary>
153 // -----------------------------------------------------------------
154 public void RegionLoaded(Scene scene)
155 {
156 if (m_enabled) {}
157 }
158
159 /// -----------------------------------------------------------------
160 /// <summary>
161 /// </summary>
162 // -----------------------------------------------------------------
163 public Type ReplaceableInterface
164 {
165 get { return null; }
166 }
167
168#endregion
169
170#region ScriptInvocationInteface
171
172 // -----------------------------------------------------------------
173 /// <summary>
174 ///
175 /// </summary>
176 // -----------------------------------------------------------------
177 public bool CreateStore(string value, out UUID result)
178 {
179 result = UUID.Zero;
180
181 if (! m_enabled) return false;
182
183 UUID uuid = UUID.Random();
184 JsonStore map = null;
185
186 try
187 {
188 map = new JsonStore(value);
189 }
190 catch (Exception e)
191 {
192 m_log.InfoFormat("[JsonStore] Unable to initialize store from {0}; {1}",value,e.Message);
193 return false;
194 }
195
196 lock (m_JsonValueStore)
197 m_JsonValueStore.Add(uuid,map);
198
199 result = uuid;
200 return true;
201 }
202
203 // -----------------------------------------------------------------
204 /// <summary>
205 ///
206 /// </summary>
207 // -----------------------------------------------------------------
208 public bool DestroyStore(UUID storeID)
209 {
210 if (! m_enabled) return false;
211
212 lock (m_JsonValueStore)
213 m_JsonValueStore.Remove(storeID);
214
215 return true;
216 }
217
218 // -----------------------------------------------------------------
219 /// <summary>
220 ///
221 /// </summary>
222 // -----------------------------------------------------------------
223 public bool TestPath(UUID storeID, string path, bool useJson)
224 {
225 if (! m_enabled) return false;
226
227 JsonStore map = null;
228 lock (m_JsonValueStore)
229 {
230 if (! m_JsonValueStore.TryGetValue(storeID,out map))
231 {
232 m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
233 return true;
234 }
235 }
236
237 try
238 {
239 lock (map)
240 return map.TestPath(path,useJson);
241 }
242 catch (Exception e)
243 {
244 m_log.InfoFormat("[JsonStore] Path test failed for {0} in {1}; {2}",path,storeID,e.Message);
245 }
246
247 return false;
248 }
249
250 // -----------------------------------------------------------------
251 /// <summary>
252 ///
253 /// </summary>
254 // -----------------------------------------------------------------
255 public bool SetValue(UUID storeID, string path, string value, bool useJson)
256 {
257 if (! m_enabled) return false;
258
259 JsonStore map = null;
260 lock (m_JsonValueStore)
261 {
262 if (! m_JsonValueStore.TryGetValue(storeID,out map))
263 {
264 m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
265 return false;
266 }
267 }
268
269 try
270 {
271 lock (map)
272 if (map.SetValue(path,value,useJson))
273 return true;
274 }
275 catch (Exception e)
276 {
277 m_log.InfoFormat("[JsonStore] Unable to assign {0} to {1} in {2}; {3}",value,path,storeID,e.Message);
278 }
279
280 return false;
281 }
282
283 // -----------------------------------------------------------------
284 /// <summary>
285 ///
286 /// </summary>
287 // -----------------------------------------------------------------
288 public bool RemoveValue(UUID storeID, string path)
289 {
290 if (! m_enabled) return false;
291
292 JsonStore map = null;
293 lock (m_JsonValueStore)
294 {
295 if (! m_JsonValueStore.TryGetValue(storeID,out map))
296 {
297 m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
298 return false;
299 }
300 }
301
302 try
303 {
304 lock (map)
305 if (map.RemoveValue(path))
306 return true;
307 }
308 catch (Exception e)
309 {
310 m_log.InfoFormat("[JsonStore] Unable to remove {0} in {1}; {2}",path,storeID,e.Message);
311 }
312
313 return false;
314 }
315
316 // -----------------------------------------------------------------
317 /// <summary>
318 ///
319 /// </summary>
320 // -----------------------------------------------------------------
321 public bool GetValue(UUID storeID, string path, bool useJson, out string value)
322 {
323 value = String.Empty;
324
325 if (! m_enabled) return false;
326
327 JsonStore map = null;
328 lock (m_JsonValueStore)
329 {
330 if (! m_JsonValueStore.TryGetValue(storeID,out map))
331 return false;
332 }
333
334 try
335 {
336 lock (map)
337 {
338 return map.GetValue(path, out value, useJson);
339 }
340 }
341 catch (Exception e)
342 {
343 m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.Message);
344 }
345
346 return false;
347 }
348
349 // -----------------------------------------------------------------
350 /// <summary>
351 ///
352 /// </summary>
353 // -----------------------------------------------------------------
354 public void TakeValue(UUID storeID, string path, bool useJson, TakeValueCallback cback)
355 {
356 if (! m_enabled)
357 {
358 cback(String.Empty);
359 return;
360 }
361
362 JsonStore map = null;
363 lock (m_JsonValueStore)
364 {
365 if (! m_JsonValueStore.TryGetValue(storeID,out map))
366 {
367 cback(String.Empty);
368 return;
369 }
370 }
371
372 try
373 {
374 lock (map)
375 {
376 map.TakeValue(path, useJson, cback);
377 return;
378 }
379 }
380 catch (Exception e)
381 {
382 m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.ToString());
383 }
384
385 cback(String.Empty);
386 }
387
388 // -----------------------------------------------------------------
389 /// <summary>
390 ///
391 /// </summary>
392 // -----------------------------------------------------------------
393 public void ReadValue(UUID storeID, string path, bool useJson, TakeValueCallback cback)
394 {
395 if (! m_enabled)
396 {
397 cback(String.Empty);
398 return;
399 }
400
401 JsonStore map = null;
402 lock (m_JsonValueStore)
403 {
404 if (! m_JsonValueStore.TryGetValue(storeID,out map))
405 {
406 cback(String.Empty);
407 return;
408 }
409 }
410
411 try
412 {
413 lock (map)
414 {
415 map.ReadValue(path, useJson, cback);
416 return;
417 }
418 }
419 catch (Exception e)
420 {
421 m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.ToString());
422 }
423
424 cback(String.Empty);
425 }
426
427#endregion
428 }
429}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
new file mode 100644
index 0000000..7aba860
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
@@ -0,0 +1,489 @@
1/*
2 * Copyright (c) Contributors
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using Mono.Addins;
28
29using System;
30using System.Reflection;
31using System.Threading;
32using System.Text;
33using System.Net;
34using System.Net.Sockets;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42using System.Collections.Generic;
43using System.Text.RegularExpressions;
44
45namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
46{
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreScriptModule")]
48
49 public class JsonStoreScriptModule : INonSharedRegionModule
50 {
51 private static readonly ILog m_log =
52 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private IConfig m_config = null;
55 private bool m_enabled = false;
56 private Scene m_scene = null;
57
58 private IScriptModuleComms m_comms;
59 private IJsonStoreModule m_store;
60
61#region IRegionModule Members
62
63 // -----------------------------------------------------------------
64 /// <summary>
65 /// Name of this shared module is it's class name
66 /// </summary>
67 // -----------------------------------------------------------------
68 public string Name
69 {
70 get { return this.GetType().Name; }
71 }
72
73 // -----------------------------------------------------------------
74 /// <summary>
75 /// Initialise this shared module
76 /// </summary>
77 /// <param name="scene">this region is getting initialised</param>
78 /// <param name="source">nini config, we are not using this</param>
79 // -----------------------------------------------------------------
80 public void Initialise(IConfigSource config)
81 {
82 try
83 {
84 if ((m_config = config.Configs["JsonStore"]) == null)
85 {
86 // There is no configuration, the module is disabled
87 m_log.InfoFormat("[JsonStoreScripts] no configuration info");
88 return;
89 }
90
91 m_enabled = m_config.GetBoolean("Enabled", m_enabled);
92 }
93 catch (Exception e)
94 {
95 m_log.ErrorFormat("[JsonStoreScripts] initialization error: {0}",e.Message);
96 return;
97 }
98
99 m_log.InfoFormat("[JsonStoreScripts] module {0} enabled",(m_enabled ? "is" : "is not"));
100 }
101
102 // -----------------------------------------------------------------
103 /// <summary>
104 /// everything is loaded, perform post load configuration
105 /// </summary>
106 // -----------------------------------------------------------------
107 public void PostInitialise()
108 {
109 }
110
111 // -----------------------------------------------------------------
112 /// <summary>
113 /// Nothing to do on close
114 /// </summary>
115 // -----------------------------------------------------------------
116 public void Close()
117 {
118 }
119
120 // -----------------------------------------------------------------
121 /// <summary>
122 /// </summary>
123 // -----------------------------------------------------------------
124 public void AddRegion(Scene scene)
125 {
126 }
127
128 // -----------------------------------------------------------------
129 /// <summary>
130 /// </summary>
131 // -----------------------------------------------------------------
132 public void RemoveRegion(Scene scene)
133 {
134 // need to remove all references to the scene in the subscription
135 // list to enable full garbage collection of the scene object
136 }
137
138 // -----------------------------------------------------------------
139 /// <summary>
140 /// Called when all modules have been added for a region. This is
141 /// where we hook up events
142 /// </summary>
143 // -----------------------------------------------------------------
144 public void RegionLoaded(Scene scene)
145 {
146 if (m_enabled)
147 {
148 m_scene = scene;
149 m_comms = m_scene.RequestModuleInterface<IScriptModuleComms>();
150 if (m_comms == null)
151 {
152 m_log.ErrorFormat("[JsonStoreScripts] ScriptModuleComms interface not defined");
153 m_enabled = false;
154 return;
155 }
156
157 m_store = m_scene.RequestModuleInterface<IJsonStoreModule>();
158 if (m_store == null)
159 {
160 m_log.ErrorFormat("[JsonStoreScripts] JsonModule interface not defined");
161 m_enabled = false;
162 return;
163 }
164
165 m_comms.RegisterScriptInvocation(this,"JsonCreateStore");
166 m_comms.RegisterScriptInvocation(this,"JsonDestroyStore");
167
168 m_comms.RegisterScriptInvocation(this,"JsonReadNotecard");
169 m_comms.RegisterScriptInvocation(this,"JsonWriteNotecard");
170
171 m_comms.RegisterScriptInvocation(this,"JsonTestPath");
172 m_comms.RegisterScriptInvocation(this,"JsonTestPathJson");
173
174 m_comms.RegisterScriptInvocation(this,"JsonGetValue");
175 m_comms.RegisterScriptInvocation(this,"JsonGetValueJson");
176
177 m_comms.RegisterScriptInvocation(this,"JsonTakeValue");
178 m_comms.RegisterScriptInvocation(this,"JsonTakeValueJson");
179
180 m_comms.RegisterScriptInvocation(this,"JsonReadValue");
181 m_comms.RegisterScriptInvocation(this,"JsonReadValueJson");
182
183 m_comms.RegisterScriptInvocation(this,"JsonSetValue");
184 m_comms.RegisterScriptInvocation(this,"JsonSetValueJson");
185
186 m_comms.RegisterScriptInvocation(this,"JsonRemoveValue");
187 }
188 }
189
190 /// -----------------------------------------------------------------
191 /// <summary>
192 /// </summary>
193 // -----------------------------------------------------------------
194 public Type ReplaceableInterface
195 {
196 get { return null; }
197 }
198
199#endregion
200
201#region ScriptInvocationInteface
202 // -----------------------------------------------------------------
203 /// <summary>
204 ///
205 /// </summary>
206 // -----------------------------------------------------------------
207 protected void GenerateRuntimeError(string msg)
208 {
209 throw new Exception("JsonStore Runtime Error: " + msg);
210 }
211
212 // -----------------------------------------------------------------
213 /// <summary>
214 ///
215 /// </summary>
216 // -----------------------------------------------------------------
217 protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value)
218 {
219 UUID uuid = UUID.Zero;
220 if (! m_store.CreateStore(value, out uuid))
221 GenerateRuntimeError("Failed to create Json store");
222
223 return uuid;
224 }
225
226 // -----------------------------------------------------------------
227 /// <summary>
228 ///
229 /// </summary>
230 // -----------------------------------------------------------------
231 protected int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID)
232 {
233 return m_store.DestroyStore(storeID) ? 1 : 0;
234 }
235
236 // -----------------------------------------------------------------
237 /// <summary>
238 ///
239 /// </summary>
240 // -----------------------------------------------------------------
241 protected UUID JsonReadNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, UUID assetID)
242 {
243 UUID reqID = UUID.Random();
244 Util.FireAndForget(delegate(object o) { DoJsonReadNotecard(reqID,hostID,scriptID,storeID,path,assetID); });
245 return reqID;
246 }
247
248 // -----------------------------------------------------------------
249 /// <summary>
250 ///
251 /// </summary>
252 // -----------------------------------------------------------------
253 protected UUID JsonWriteNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, string name)
254 {
255 UUID reqID = UUID.Random();
256 Util.FireAndForget(delegate(object o) { DoJsonWriteNotecard(reqID,hostID,scriptID,storeID,path,name); });
257 return reqID;
258 }
259
260 // -----------------------------------------------------------------
261 /// <summary>
262 ///
263 /// </summary>
264 // -----------------------------------------------------------------
265 protected int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path)
266 {
267 return m_store.TestPath(storeID,path,false) ? 1 : 0;
268 }
269
270 protected int JsonTestPathJson(UUID hostID, UUID scriptID, UUID storeID, string path)
271 {
272 return m_store.TestPath(storeID,path,true) ? 1 : 0;
273 }
274
275 // -----------------------------------------------------------------
276 /// <summary>
277 ///
278 /// </summary>
279 // -----------------------------------------------------------------
280 protected int JsonSetValue(UUID hostID, UUID scriptID, UUID storeID, string path, string value)
281 {
282 return m_store.SetValue(storeID,path,value,false) ? 1 : 0;
283 }
284
285 protected int JsonSetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path, string value)
286 {
287 return m_store.SetValue(storeID,path,value,true) ? 1 : 0;
288 }
289
290 // -----------------------------------------------------------------
291 /// <summary>
292 ///
293 /// </summary>
294 // -----------------------------------------------------------------
295 protected int JsonRemoveValue(UUID hostID, UUID scriptID, UUID storeID, string path)
296 {
297 return m_store.RemoveValue(storeID,path) ? 1 : 0;
298 }
299
300 // -----------------------------------------------------------------
301 /// <summary>
302 ///
303 /// </summary>
304 // -----------------------------------------------------------------
305 protected string JsonGetValue(UUID hostID, UUID scriptID, UUID storeID, string path)
306 {
307 string value = String.Empty;
308 m_store.GetValue(storeID,path,false,out value);
309 return value;
310 }
311
312 protected string JsonGetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
313 {
314 string value = String.Empty;
315 m_store.GetValue(storeID,path,true, out value);
316 return value;
317 }
318
319 // -----------------------------------------------------------------
320 /// <summary>
321 ///
322 /// </summary>
323 // -----------------------------------------------------------------
324 protected UUID JsonTakeValue(UUID hostID, UUID scriptID, UUID storeID, string path)
325 {
326 UUID reqID = UUID.Random();
327 Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,false); });
328 return reqID;
329 }
330
331 protected UUID JsonTakeValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
332 {
333 UUID reqID = UUID.Random();
334 Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,true); });
335 return reqID;
336 }
337
338 private void DoJsonTakeValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson)
339 {
340 try
341 {
342 m_store.TakeValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); });
343 return;
344 }
345 catch (Exception e)
346 {
347 m_log.InfoFormat("[JsonStoreScripts] unable to retrieve value; {0}",e.ToString());
348 }
349
350 DispatchValue(scriptID,reqID,String.Empty);
351 }
352
353
354 // -----------------------------------------------------------------
355 /// <summary>
356 ///
357 /// </summary>
358 // -----------------------------------------------------------------
359 protected UUID JsonReadValue(UUID hostID, UUID scriptID, UUID storeID, string path)
360 {
361 UUID reqID = UUID.Random();
362 Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,false); });
363 return reqID;
364 }
365
366 protected UUID JsonReadValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
367 {
368 UUID reqID = UUID.Random();
369 Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,true); });
370 return reqID;
371 }
372
373 private void DoJsonReadValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson)
374 {
375 try
376 {
377 m_store.ReadValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); });
378 return;
379 }
380 catch (Exception e)
381 {
382 m_log.InfoFormat("[JsonStoreScripts] unable to retrieve value; {0}",e.ToString());
383 }
384
385 DispatchValue(scriptID,reqID,String.Empty);
386 }
387
388#endregion
389
390 // -----------------------------------------------------------------
391 /// <summary>
392 ///
393 /// </summary>
394 // -----------------------------------------------------------------
395 protected void DispatchValue(UUID scriptID, UUID reqID, string value)
396 {
397 m_comms.DispatchReply(scriptID,1,value,reqID.ToString());
398 }
399
400 // -----------------------------------------------------------------
401 /// <summary>
402 ///
403 /// </summary>
404 // -----------------------------------------------------------------
405 private void DoJsonReadNotecard(UUID reqID, UUID hostID, UUID scriptID, UUID storeID, string path, UUID assetID)
406 {
407 AssetBase a = m_scene.AssetService.Get(assetID.ToString());
408 if (a == null)
409 GenerateRuntimeError(String.Format("Unable to find notecard asset {0}",assetID));
410
411 if (a.Type != (sbyte)AssetType.Notecard)
412 GenerateRuntimeError(String.Format("Invalid notecard asset {0}",assetID));
413
414 m_log.DebugFormat("[JsonStoreScripts] read notecard in context {0}",storeID);
415
416 try
417 {
418 System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
419 string jsondata = SLUtil.ParseNotecardToString(enc.GetString(a.Data));
420 int result = m_store.SetValue(storeID,path,jsondata,true) ? 1 : 0;
421 m_comms.DispatchReply(scriptID,result,"",reqID.ToString());
422 return;
423 }
424 catch (Exception e)
425 {
426 m_log.WarnFormat("[JsonStoreScripts] Json parsing failed; {0}",e.Message);
427 }
428
429 GenerateRuntimeError(String.Format("Json parsing failed for {0}",assetID.ToString()));
430 m_comms.DispatchReply(scriptID,0,"",reqID.ToString());
431 }
432
433 // -----------------------------------------------------------------
434 /// <summary>
435 ///
436 /// </summary>
437 // -----------------------------------------------------------------
438 private void DoJsonWriteNotecard(UUID reqID, UUID hostID, UUID scriptID, UUID storeID, string path, string name)
439 {
440 string data;
441 if (! m_store.GetValue(storeID,path,true, out data))
442 {
443 m_comms.DispatchReply(scriptID,0,UUID.Zero.ToString(),reqID.ToString());
444 return;
445 }
446
447 SceneObjectPart host = m_scene.GetSceneObjectPart(hostID);
448
449 // Create new asset
450 UUID assetID = UUID.Random();
451 AssetBase asset = new AssetBase(assetID, name, (sbyte)AssetType.Notecard, host.OwnerID.ToString());
452 asset.Description = "Json store";
453
454 int textLength = data.Length;
455 data = "Linden text version 2\n{\nLLEmbeddedItems version 1\n{\ncount 0\n}\nText length "
456 + textLength.ToString() + "\n" + data + "}\n";
457
458 asset.Data = Util.UTF8.GetBytes(data);
459 m_scene.AssetService.Store(asset);
460
461 // Create Task Entry
462 TaskInventoryItem taskItem = new TaskInventoryItem();
463
464 taskItem.ResetIDs(host.UUID);
465 taskItem.ParentID = host.UUID;
466 taskItem.CreationDate = (uint)Util.UnixTimeSinceEpoch();
467 taskItem.Name = asset.Name;
468 taskItem.Description = asset.Description;
469 taskItem.Type = (int)AssetType.Notecard;
470 taskItem.InvType = (int)InventoryType.Notecard;
471 taskItem.OwnerID = host.OwnerID;
472 taskItem.CreatorID = host.OwnerID;
473 taskItem.BasePermissions = (uint)PermissionMask.All;
474 taskItem.CurrentPermissions = (uint)PermissionMask.All;
475 taskItem.EveryonePermissions = 0;
476 taskItem.NextPermissions = (uint)PermissionMask.All;
477 taskItem.GroupID = host.GroupID;
478 taskItem.GroupPermissions = 0;
479 taskItem.Flags = 0;
480 taskItem.PermsGranter = UUID.Zero;
481 taskItem.PermsMask = 0;
482 taskItem.AssetID = asset.FullID;
483
484 host.Inventory.AddInventoryItem(taskItem, false);
485
486 m_comms.DispatchReply(scriptID,1,assetID.ToString(),reqID.ToString());
487 }
488 }
489}