JsonStore.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  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. */
  27. using Mono.Addins;
  28. using System;
  29. using System.Reflection;
  30. using System.Threading;
  31. using System.Text;
  32. using System.Net;
  33. using System.Net.Sockets;
  34. using log4net;
  35. using Nini.Config;
  36. using OpenMetaverse;
  37. using OpenMetaverse.StructuredData;
  38. using OpenSim.Framework;
  39. using OpenSim.Region.Framework.Interfaces;
  40. using OpenSim.Region.Framework.Scenes;
  41. using System.Collections.Generic;
  42. using System.Text.RegularExpressions;
  43. namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
  44. {
  45. public class JsonStore
  46. {
  47. private static readonly ILog m_log =
  48. LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  49. protected virtual OSD ValueStore { get; set; }
  50. protected class TakeValueCallbackClass
  51. {
  52. public string Path { get; set; }
  53. public bool UseJson { get; set; }
  54. public TakeValueCallback Callback { get; set; }
  55. public TakeValueCallbackClass(string spath, bool usejson, TakeValueCallback cback)
  56. {
  57. Path = spath;
  58. UseJson = usejson;
  59. Callback = cback;
  60. }
  61. }
  62. protected List<TakeValueCallbackClass> m_TakeStore;
  63. protected List<TakeValueCallbackClass> m_ReadStore;
  64. // add separators for quoted paths and array references
  65. protected static Regex m_ParsePassOne = new Regex("({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])");
  66. // add quotes to bare identifiers which are limited to alphabetic characters
  67. protected static Regex m_ParsePassThree = new Regex("(?<!{[^}]*)\\.([a-zA-Z]+)(?=\\.)");
  68. // remove extra separator characters
  69. protected static Regex m_ParsePassFour = new Regex("\\.+");
  70. // expression used to validate the full path, this is canonical representation
  71. protected static Regex m_ValidatePath = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)*$");
  72. // expression used to match path components
  73. protected static Regex m_PathComponent = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])");
  74. // extract the internals of an array reference
  75. protected static Regex m_SimpleArrayPattern = new Regex("^\\[([0-9]+)\\]$");
  76. protected static Regex m_ArrayPattern = new Regex("^\\[([0-9]+|\\+)\\]$");
  77. // extract the internals of a has reference
  78. protected static Regex m_HashPattern = new Regex("^{([^}]+)}$");
  79. // -----------------------------------------------------------------
  80. /// <summary>
  81. /// This is a simple estimator for the size of the stored data, it
  82. /// is not precise, but should be close enough to implement reasonable
  83. /// limits on the storage space used
  84. /// </summary>
  85. // -----------------------------------------------------------------
  86. public int StringSpace { get; set; }
  87. // -----------------------------------------------------------------
  88. /// <summary>
  89. ///
  90. /// </summary>
  91. // -----------------------------------------------------------------
  92. public static bool CanonicalPathExpression(string ipath, out string opath)
  93. {
  94. Stack<string> path;
  95. if (! ParsePathExpression(ipath,out path))
  96. {
  97. opath = "";
  98. return false;
  99. }
  100. opath = PathExpressionToKey(path);
  101. return true;
  102. }
  103. // -----------------------------------------------------------------
  104. /// <summary>
  105. ///
  106. /// </summary>
  107. // -----------------------------------------------------------------
  108. public JsonStore()
  109. {
  110. StringSpace = 0;
  111. m_TakeStore = new List<TakeValueCallbackClass>();
  112. m_ReadStore = new List<TakeValueCallbackClass>();
  113. }
  114. public JsonStore(string value) : this()
  115. {
  116. // This is going to throw an exception if the value is not
  117. // a valid JSON chunk. Calling routines should catch the
  118. // exception and handle it appropriately
  119. if (String.IsNullOrEmpty(value))
  120. ValueStore = new OSDMap();
  121. else
  122. ValueStore = OSDParser.DeserializeJson(value);
  123. }
  124. // -----------------------------------------------------------------
  125. /// <summary>
  126. ///
  127. /// </summary>
  128. // -----------------------------------------------------------------
  129. public JsonStoreNodeType GetNodeType(string expr)
  130. {
  131. Stack<string> path;
  132. if (! ParsePathExpression(expr,out path))
  133. return JsonStoreNodeType.Undefined;
  134. OSD result = ProcessPathExpression(ValueStore,path);
  135. if (result == null)
  136. return JsonStoreNodeType.Undefined;
  137. if (result is OSDMap)
  138. return JsonStoreNodeType.Object;
  139. if (result is OSDArray)
  140. return JsonStoreNodeType.Array;
  141. if (OSDBaseType(result.Type))
  142. return JsonStoreNodeType.Value;
  143. return JsonStoreNodeType.Undefined;
  144. }
  145. // -----------------------------------------------------------------
  146. /// <summary>
  147. ///
  148. /// </summary>
  149. // -----------------------------------------------------------------
  150. public JsonStoreValueType GetValueType(string expr)
  151. {
  152. Stack<string> path;
  153. if (! ParsePathExpression(expr,out path))
  154. return JsonStoreValueType.Undefined;
  155. OSD result = ProcessPathExpression(ValueStore,path);
  156. if (result == null)
  157. return JsonStoreValueType.Undefined;
  158. if (result is OSDMap)
  159. return JsonStoreValueType.Undefined;
  160. if (result is OSDArray)
  161. return JsonStoreValueType.Undefined;
  162. if (result is OSDBoolean)
  163. return JsonStoreValueType.Boolean;
  164. if (result is OSDInteger)
  165. return JsonStoreValueType.Integer;
  166. if (result is OSDReal)
  167. return JsonStoreValueType.Float;
  168. if (result is OSDString)
  169. return JsonStoreValueType.String;
  170. return JsonStoreValueType.Undefined;
  171. }
  172. // -----------------------------------------------------------------
  173. /// <summary>
  174. ///
  175. /// </summary>
  176. // -----------------------------------------------------------------
  177. public int ArrayLength(string expr)
  178. {
  179. Stack<string> path;
  180. if (! ParsePathExpression(expr,out path))
  181. return -1;
  182. OSD result = ProcessPathExpression(ValueStore,path);
  183. if (result != null && result.Type == OSDType.Array)
  184. {
  185. OSDArray arr = result as OSDArray;
  186. return arr.Count;
  187. }
  188. return -1;
  189. }
  190. // -----------------------------------------------------------------
  191. /// <summary>
  192. ///
  193. /// </summary>
  194. // -----------------------------------------------------------------
  195. public bool GetValue(string expr, out string value, bool useJson)
  196. {
  197. Stack<string> path;
  198. if (! ParsePathExpression(expr,out path))
  199. {
  200. value = "";
  201. return false;
  202. }
  203. OSD result = ProcessPathExpression(ValueStore,path);
  204. return ConvertOutputValue(result,out value,useJson);
  205. }
  206. // -----------------------------------------------------------------
  207. /// <summary>
  208. ///
  209. /// </summary>
  210. // -----------------------------------------------------------------
  211. public bool RemoveValue(string expr)
  212. {
  213. return SetValueFromExpression(expr,null);
  214. }
  215. // -----------------------------------------------------------------
  216. /// <summary>
  217. ///
  218. /// </summary>
  219. // -----------------------------------------------------------------
  220. public bool SetValue(string expr, string value, bool useJson)
  221. {
  222. OSD ovalue;
  223. // One note of caution... if you use an empty string in the
  224. // structure it will be assumed to be a default value and will
  225. // not be seialized in the json
  226. if (useJson)
  227. {
  228. // There doesn't appear to be a good way to determine if the
  229. // value is valid Json other than to let the parser crash
  230. try
  231. {
  232. ovalue = OSDParser.DeserializeJson(value);
  233. }
  234. catch (Exception)
  235. {
  236. if (value.StartsWith("'") && value.EndsWith("'"))
  237. {
  238. ovalue = new OSDString(value.Substring(1,value.Length - 2));
  239. }
  240. else
  241. {
  242. return false;
  243. }
  244. }
  245. }
  246. else
  247. {
  248. ovalue = new OSDString(value);
  249. }
  250. return SetValueFromExpression(expr,ovalue);
  251. }
  252. // -----------------------------------------------------------------
  253. /// <summary>
  254. ///
  255. /// </summary>
  256. // -----------------------------------------------------------------
  257. public bool TakeValue(string expr, bool useJson, TakeValueCallback cback)
  258. {
  259. Stack<string> path;
  260. if (! ParsePathExpression(expr,out path))
  261. return false;
  262. string pexpr = PathExpressionToKey(path);
  263. OSD result = ProcessPathExpression(ValueStore,path);
  264. if (result == null)
  265. {
  266. m_TakeStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
  267. return false;
  268. }
  269. string value = String.Empty;
  270. if (! ConvertOutputValue(result,out value,useJson))
  271. {
  272. // the structure does not match the request so i guess we'll wait
  273. m_TakeStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
  274. return false;
  275. }
  276. SetValueFromExpression(expr,null);
  277. cback(value);
  278. return true;
  279. }
  280. // -----------------------------------------------------------------
  281. /// <summary>
  282. ///
  283. /// </summary>
  284. // -----------------------------------------------------------------
  285. public bool ReadValue(string expr, bool useJson, TakeValueCallback cback)
  286. {
  287. Stack<string> path;
  288. if (! ParsePathExpression(expr,out path))
  289. return false;
  290. string pexpr = PathExpressionToKey(path);
  291. OSD result = ProcessPathExpression(ValueStore,path);
  292. if (result == null)
  293. {
  294. m_ReadStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
  295. return false;
  296. }
  297. string value = String.Empty;
  298. if (! ConvertOutputValue(result,out value,useJson))
  299. {
  300. // the structure does not match the request so i guess we'll wait
  301. m_ReadStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback));
  302. return false;
  303. }
  304. cback(value);
  305. return true;
  306. }
  307. // -----------------------------------------------------------------
  308. /// <summary>
  309. ///
  310. /// </summary>
  311. // -----------------------------------------------------------------
  312. protected bool SetValueFromExpression(string expr, OSD ovalue)
  313. {
  314. Stack<string> path;
  315. if (! ParsePathExpression(expr,out path))
  316. return false;
  317. if (path.Count == 0)
  318. {
  319. ValueStore = ovalue;
  320. StringSpace = 0;
  321. return true;
  322. }
  323. // pkey will be the final element in the path, we pull it out here to make sure
  324. // that the assignment works correctly
  325. string pkey = path.Pop();
  326. string pexpr = PathExpressionToKey(path);
  327. if (pexpr != "")
  328. pexpr += ".";
  329. OSD result = ProcessPathExpression(ValueStore,path);
  330. if (result == null)
  331. return false;
  332. // Check pkey, the last element in the path, for and extract array references
  333. MatchCollection amatches = m_ArrayPattern.Matches(pkey,0);
  334. if (amatches.Count > 0)
  335. {
  336. if (result.Type != OSDType.Array)
  337. return false;
  338. OSDArray amap = result as OSDArray;
  339. Match match = amatches[0];
  340. GroupCollection groups = match.Groups;
  341. string akey = groups[1].Value;
  342. if (akey == "+")
  343. {
  344. string npkey = String.Format("[{0}]",amap.Count);
  345. if (ovalue != null)
  346. {
  347. StringSpace += ComputeSizeOf(ovalue);
  348. amap.Add(ovalue);
  349. InvokeNextCallback(pexpr + npkey);
  350. }
  351. return true;
  352. }
  353. int aval = Convert.ToInt32(akey);
  354. if (0 <= aval && aval < amap.Count)
  355. {
  356. if (ovalue == null)
  357. {
  358. StringSpace -= ComputeSizeOf(amap[aval]);
  359. amap.RemoveAt(aval);
  360. }
  361. else
  362. {
  363. StringSpace -= ComputeSizeOf(amap[aval]);
  364. StringSpace += ComputeSizeOf(ovalue);
  365. amap[aval] = ovalue;
  366. InvokeNextCallback(pexpr + pkey);
  367. }
  368. return true;
  369. }
  370. return false;
  371. }
  372. // Check for and extract hash references
  373. MatchCollection hmatches = m_HashPattern.Matches(pkey,0);
  374. if (hmatches.Count > 0)
  375. {
  376. Match match = hmatches[0];
  377. GroupCollection groups = match.Groups;
  378. string hkey = groups[1].Value;
  379. if (result is OSDMap)
  380. {
  381. // this is the assignment case
  382. OSDMap hmap = result as OSDMap;
  383. if (ovalue != null)
  384. {
  385. StringSpace -= ComputeSizeOf(hmap[hkey]);
  386. StringSpace += ComputeSizeOf(ovalue);
  387. hmap[hkey] = ovalue;
  388. InvokeNextCallback(pexpr + pkey);
  389. return true;
  390. }
  391. // this is the remove case
  392. if (hmap.ContainsKey(hkey))
  393. {
  394. StringSpace -= ComputeSizeOf(hmap[hkey]);
  395. hmap.Remove(hkey);
  396. return true;
  397. }
  398. return false;
  399. }
  400. return false;
  401. }
  402. // Shouldn't get here if the path was checked correctly
  403. m_log.WarnFormat("[JsonStore] invalid path expression");
  404. return false;
  405. }
  406. // -----------------------------------------------------------------
  407. /// <summary>
  408. ///
  409. /// </summary>
  410. // -----------------------------------------------------------------
  411. protected bool InvokeNextCallback(string pexpr)
  412. {
  413. // Process all of the reads that match the expression first
  414. List<TakeValueCallbackClass> reads =
  415. m_ReadStore.FindAll(delegate(TakeValueCallbackClass tb) { return pexpr.StartsWith(tb.Path); });
  416. foreach (TakeValueCallbackClass readcb in reads)
  417. {
  418. m_ReadStore.Remove(readcb);
  419. ReadValue(readcb.Path,readcb.UseJson,readcb.Callback);
  420. }
  421. // Process one take next
  422. TakeValueCallbackClass takecb =
  423. m_TakeStore.Find(delegate(TakeValueCallbackClass tb) { return pexpr.StartsWith(tb.Path); });
  424. if (takecb != null)
  425. {
  426. m_TakeStore.Remove(takecb);
  427. TakeValue(takecb.Path,takecb.UseJson,takecb.Callback);
  428. return true;
  429. }
  430. return false;
  431. }
  432. // -----------------------------------------------------------------
  433. /// <summary>
  434. /// Parse the path expression and put the components into a stack. We
  435. /// use a stack because we process the path in inverse order later
  436. /// </summary>
  437. // -----------------------------------------------------------------
  438. protected static bool ParsePathExpression(string expr, out Stack<string> path)
  439. {
  440. path = new Stack<string>();
  441. // add front and rear separators
  442. expr = "." + expr + ".";
  443. // add separators for quoted exprs and array references
  444. expr = m_ParsePassOne.Replace(expr,".$1.",-1,0);
  445. // add quotes to bare identifier
  446. expr = m_ParsePassThree.Replace(expr,".{$1}",-1,0);
  447. // remove extra separators
  448. expr = m_ParsePassFour.Replace(expr,".",-1,0);
  449. // validate the results (catches extra quote characters for example)
  450. if (m_ValidatePath.IsMatch(expr))
  451. {
  452. MatchCollection matches = m_PathComponent.Matches(expr,0);
  453. foreach (Match match in matches)
  454. path.Push(match.Groups[1].Value);
  455. return true;
  456. }
  457. return false;
  458. }
  459. // -----------------------------------------------------------------
  460. /// <summary>
  461. ///
  462. /// </summary>
  463. /// <param>path is a stack where the top level of the path is at the bottom of the stack</param>
  464. // -----------------------------------------------------------------
  465. protected static OSD ProcessPathExpression(OSD map, Stack<string> path)
  466. {
  467. if (path.Count == 0)
  468. return map;
  469. string pkey = path.Pop();
  470. OSD rmap = ProcessPathExpression(map,path);
  471. if (rmap == null)
  472. return null;
  473. // ---------- Check for an array index ----------
  474. MatchCollection amatches = m_SimpleArrayPattern.Matches(pkey,0);
  475. if (amatches.Count > 0)
  476. {
  477. if (rmap.Type != OSDType.Array)
  478. {
  479. m_log.WarnFormat("[JsonStore] wrong type for key {2}, expecting {0}, got {1}",OSDType.Array,rmap.Type,pkey);
  480. return null;
  481. }
  482. OSDArray amap = rmap as OSDArray;
  483. Match match = amatches[0];
  484. GroupCollection groups = match.Groups;
  485. string akey = groups[1].Value;
  486. int aval = Convert.ToInt32(akey);
  487. if (aval < amap.Count)
  488. return (OSD) amap[aval];
  489. return null;
  490. }
  491. // ---------- Check for a hash index ----------
  492. MatchCollection hmatches = m_HashPattern.Matches(pkey,0);
  493. if (hmatches.Count > 0)
  494. {
  495. if (rmap.Type != OSDType.Map)
  496. {
  497. m_log.WarnFormat("[JsonStore] wrong type for key {2}, expecting {0}, got {1}",OSDType.Map,rmap.Type,pkey);
  498. return null;
  499. }
  500. OSDMap hmap = rmap as OSDMap;
  501. Match match = hmatches[0];
  502. GroupCollection groups = match.Groups;
  503. string hkey = groups[1].Value;
  504. if (hmap.ContainsKey(hkey))
  505. return (OSD) hmap[hkey];
  506. return null;
  507. }
  508. // Shouldn't get here if the path was checked correctly
  509. m_log.WarnFormat("[JsonStore] Path type (unknown) does not match the structure");
  510. return null;
  511. }
  512. // -----------------------------------------------------------------
  513. /// <summary>
  514. ///
  515. /// </summary>
  516. // -----------------------------------------------------------------
  517. protected static bool ConvertOutputValue(OSD result, out string value, bool useJson)
  518. {
  519. value = String.Empty;
  520. // If we couldn't process the path
  521. if (result == null)
  522. return false;
  523. if (useJson)
  524. {
  525. // The path pointed to an intermediate hash structure
  526. if (result.Type == OSDType.Map)
  527. {
  528. value = OSDParser.SerializeJsonString(result as OSDMap,true);
  529. return true;
  530. }
  531. // The path pointed to an intermediate hash structure
  532. if (result.Type == OSDType.Array)
  533. {
  534. value = OSDParser.SerializeJsonString(result as OSDArray,true);
  535. return true;
  536. }
  537. value = "'" + result.AsString() + "'";
  538. return true;
  539. }
  540. if (OSDBaseType(result.Type))
  541. {
  542. value = result.AsString();
  543. return true;
  544. }
  545. return false;
  546. }
  547. // -----------------------------------------------------------------
  548. /// <summary>
  549. ///
  550. /// </summary>
  551. // -----------------------------------------------------------------
  552. protected static string PathExpressionToKey(Stack<string> path)
  553. {
  554. if (path.Count == 0)
  555. return "";
  556. string pkey = "";
  557. foreach (string k in path)
  558. pkey = (pkey == "") ? k : (k + "." + pkey);
  559. return pkey;
  560. }
  561. // -----------------------------------------------------------------
  562. /// <summary>
  563. ///
  564. /// </summary>
  565. // -----------------------------------------------------------------
  566. protected static bool OSDBaseType(OSDType type)
  567. {
  568. // Should be the list of base types for which AsString() returns
  569. // something useful
  570. if (type == OSDType.Boolean)
  571. return true;
  572. if (type == OSDType.Integer)
  573. return true;
  574. if (type == OSDType.Real)
  575. return true;
  576. if (type == OSDType.String)
  577. return true;
  578. if (type == OSDType.UUID)
  579. return true;
  580. if (type == OSDType.Date)
  581. return true;
  582. if (type == OSDType.URI)
  583. return true;
  584. return false;
  585. }
  586. // -----------------------------------------------------------------
  587. /// <summary>
  588. ///
  589. /// </summary>
  590. // -----------------------------------------------------------------
  591. protected static int ComputeSizeOf(OSD value)
  592. {
  593. string sval;
  594. if (ConvertOutputValue(value,out sval,true))
  595. return sval.Length;
  596. return 0;
  597. }
  598. }
  599. // -----------------------------------------------------------------
  600. /// <summary>
  601. /// </summary>
  602. // -----------------------------------------------------------------
  603. public class JsonObjectStore : JsonStore
  604. {
  605. private static readonly ILog m_log =
  606. LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  607. private Scene m_scene;
  608. private UUID m_objectID;
  609. protected override OSD ValueStore
  610. {
  611. get
  612. {
  613. SceneObjectPart sop = m_scene.GetSceneObjectPart(m_objectID);
  614. if (sop == null)
  615. {
  616. // This is bad
  617. return null;
  618. }
  619. return sop.DynAttrs.TopLevelMap;
  620. }
  621. // cannot set the top level
  622. set
  623. {
  624. m_log.InfoFormat("[JsonStore] cannot set top level value in object store");
  625. }
  626. }
  627. public JsonObjectStore(Scene scene, UUID oid) : base()
  628. {
  629. m_scene = scene;
  630. m_objectID = oid;
  631. // the size limit is imposed on whatever is already in the store
  632. StringSpace = ComputeSizeOf(ValueStore);
  633. }
  634. }
  635. }